# encoding: UTF-8

require 'tempfile'
require 'mini_magick'
require 'delegate'


module Spontaneous::Field
  class Image < File
    autoload :Size, 'spontaneous/field/image/size'

    include Spontaneous::Media::Image::Renderable

    has_editor

    def self.accepts
      %w{image/(png|jpeg|gif)}
    end

    class TemplateParameters < DelegateClass(S::Media::Image::Attributes)
      attr_reader :image

      def initialize(image, args)
        super(image)
        @image, @args = image, args.extract_options!
      end

      def to_html(attributes = {})
        @image.to_html(@args.merge(attributes))
      end
    end

    def self.size(name, options = {}, &process)
      self.sizes[name.to_sym] = [options, process]
      unless method_defined?(name)
        class_eval "def #{name}(*args); TemplateParameters.new(sizes[:#{name}], args); end"
      end
    end

    def self.sizes
      size_definitions
    end

    def self.validate_sizes(sizes)
      sizes
    end

    def self.size_definitions
      @size_definitions ||= superclass.respond_to?(:size_definitions) ? superclass.size_definitions.dup : default_size_definitions
    end

    def self.default_size_definitions
      { :original => original_size, :__ui__ => ui_preview_size }
    end

    def self.original_size
      [ {} ]
    end

    def self.ui_preview_size
      [ {}, proc { width 300 } ]
    end

    def image?
      true
    end

    def sizes
      @sizes ||= Hash.new { |hash, key| hash[key] = S::Media::Image::Attributes.new(processed_values[key]) }
    end

    # value used to show conflicts between the current value and the value they're attempting to enter
    def conflicted_value
      value
    end

    # I want to merge the file info available in the media file
    # with the image details (width, height etc)
    def serialize_pending_file(file)
      attrs = file.serialize
      url   = attrs.delete(:url)
      image = Spontaneous::Media::Image.new(file.path)
      attrs.merge(image.serialize).merge(super)
    end

    def page_lock_description
      "Processing image '#{pending_value[:value][:filename]}'"
    end

    # original is special and should always be defined
    def original
      @original ||= sizes[:original]
    end

    def width
      original.width
    end

    def height
      original.height
    end

    def filesize
      original.filesize
    end

    def src
      original.src
    end

    def filepath
      unprocessed_value
    end

    # formats are irrelevant to image/file fields
    def outputs
      [:original, :__ui__].concat(self.class.size_definitions.map { |name, process| name })
    end

    def value(format=:html, *args)
      sizes[:original].src
    end

    def set_value!(value, process = true)
      @sizes = nil
      super
    end

    def generate(name, media_file)
      return { :src => media_file } if media_file.is_a?(::String)
      options, process = self.class.size_definitions[name]
      size = Size.new(media_file, name, options, process)
      size.generate
    end


    def export(user = nil)
      super(user).merge({
        :processed_value => processed_values
      })
    end

    self.register(:image, :photo)
  end
end