require 'amrita2/template'

require 'action_view'

module Amrita2
  module Core
    class Hook
      include ActionView::Helpers::FormHelper
      include ActionView::Helpers::FormHelper
    end
  end

end

module Amrita2View # :nodoc: all
  module FormHelper
    class FormFieldHelper
      include Amrita2::DictionaryData
      attr_reader :form, :data
      
      def initialize(record, form, &block)
        @record = record
        @form = form
        @data = {}
        block.call(self)
      end

      def add_field(name, value)
        @data[name] = value
      end

      def add_field_element(name, element)
        add_field(name, Amrita2::SanitizedString[element])
      end

      def method_missing(meth, name, *args, &block)
        value = @form.send(meth, name, *args, &block)
        add_field_element(name, value)
      end

      def as_hash
        @data
      end

      def as_label_field_hash
        @data.inject(Hash.new) do |h, data|
          k, v = *data
          h.merge ({
                     k => {
                       :label => {
                         :for=>"#{@record}_#{k}",
                         :text=>k.to_s
                       },
                       :field => v
                     }
                   })
        end
      end
    end
    
    def amrita_define_form(*args, &block)
      record = args.first
      method = :form_for
      format = :as_hash
      case h = args.last
      when Hash
        method = h.delete(:form_method) || method
        format = h.delete(:amrita_format) || format
      end

      amrita_form_hook(method, *args) do |f|
        FormFieldHelper.new(record, f) do |ff|
          block.call(ff)
        end.send(format)
      end
    end
    
    def amrita_form_hook(meth, *args, &block)
      view = self
      hook = Amrita2::Core::Hook.new do
        _erbout = stream
        view.instance_eval do
          self.send(meth, *args) do |f|
            data = block.call(f)
            hook.render_me_with(data)
          end
        end
      end
    end
  end
  FormFieldHelper = FormHelper::FormFieldHelper
end

module ActionView # :nodoc: all
  class Base #:nodoc:
    include Amrita2::Runtime
    include Amrita2View::FormHelper
  end
end

module ActiveRecord # :nodoc: all
  class Base
    include Amrita2::DictionaryData
  end
  
  class ConnectionAdapters::Column 
    include Amrita2::DictionaryData
  end
end

module Amrita2View # :nodoc: all
  class Base
    include Amrita2
    include Amrita2::Filters
    include Amrita2::Runtime
    include Amrita2::Util

    CompileTimeBinding = binding
    @@compiled_amrita2_templates = {}

    @@text_domain = nil
    cattr_accessor :text_domain

    def initialize( action_view )
      @action_view = action_view
    end

    def render(template, local_assigns={})
      Thread::current[:amrita_rails_view] = @action_view
      if template.kind_of?(String)
        render_amrita(template, local_assigns)
      else
        @action_view.render(template, local_assigns)
      end
    end

    def setup_template(template)
      setup_template_default(template)
    end

    def setup_template_default(template)
      if Amrita2::const_defined?(:GetTextBridge)
        t = Amrita2::Template.new(template) do |e, src, filters|
          filters << Amrita2::Filters::GetTextFilter.new
        end
        t.text_domain = text_domain
        bindtextdomain(t.text_domain)
        #t.set_trace(STDOUT)
        t.compiletime_binding = CompileTimeBinding
        t
      else
        t = Amrita2::Template.new(template)
        t.compiletime_binding = CompileTimeBinding
        t
      end
    end

    def render_amrita(template, local_assigns)
      @@compiled_amrita2_templates[template] ||= setup_template(template)
      tmpl = @@compiled_amrita2_templates[template]
      b = setup_binding_of_view(local_assigns)
      tmpl.render_with(b)
    end

    def setup_binding_of_view(local_assigns)
      @action_view.instance_eval do
        evaluate_assigns
        b = binding
        local_assigns.each do |k, v|
          amrita_set_context_value(v)
          eval "#{k}=amrita_get_context_value",b
        end
        b
      end
    end
  end

  
  module Helper
    include ActionView::Helpers::UrlHelper

    def view
      @view ||=  Thread::current[:amrita_rails_view]
    end

    def eval_in_view(&block)
      view.instance_eval &block
    end

    def eval_in_view_without_escape(&block)
      Amrita2::SanitizedString[eval_in_view(&block)]
    end
  end
end

=begin

  class WithObject < Amrita2::Macro::Base
    TemplateText = <<-'END'
      <<%<
        <% Thread::current[:amrita2_form_object] = $_[:name] || $_[:object] %>
      <<_ :| Attr[:target_src=>:object]<
        <<:contents>>
    END

    Option = {
      :tag => "a:with_object",
      :use_contents => :contents,
    }

  end

  class Input < Amrita2::Macro::Base
    TemplateText = <<-'END'
      <<%<
        <%
          object = $_.delete(:object) || Thread::current[:amrita2_form_object]
          input_id  = $_.delete(:id)
          other = $_.collect do |k, v|
            "#{k}='#{v}'"
          end
         %>
        <input id="<%= object %>_<%= input_id %>" name="<%= object %>[<%= input_id%>]" <%= other %> target_filter="Attr[:value=><%= input_id.intern.inspect %>]"/>
    END

    Option = {
      :tag => "a:input"
    }
  end

  class TextField < Amrita2::Macro::Base
    TemplateText = <<-'END'
      <<%<
        <%
          object = $_.delete(:object) || Thread::current[:amrita2_form_object]
          input_id  = $_.delete(:id)
          $_[:size] ||= 30
          other = $_.collect do |k, v|
            "#{k}='#{v}'"
          end
         %>
        <input type="text" id="<%= object %>_<%= input_id %>" name="<%= object %>[<%= input_id%>]" <%= other %> target_filter="Attr[:value=><%= input_id.intern.inspect %>]"/>
    END

    Option = {
      :tag => "a:text_field",
    }
  end

  class TextArea < Amrita2::Macro::Base
    TemplateText = <<-'END'
      <<%<
        <%
          object = $_.delete(:object) || Thread::current[:amrita2_form_object]
          input_id  = $_.delete(:id)
          $_[:cols] ||= 40
          $_[:rows] ||= 20
          other = $_.collect do |k, v|
            "#{k}='#{v}'"
          end
         %>
        <textarea id="<%= object %>_<%= input_id %>" name="<%= object %>[<%= input_id%>]" <%= other %> target_filter="Attr[:body=><%= input_id.intern.inspect %>]"/>
    END

    Option = {
      :tag => "a:textarea",
    }
  end
=end