module OrbitTag

  module Merging
    
    protected

    def clone_tag(module_tag, parent_id=nil, set_parent=nil)
      new_tag = module_tag.clone
      new_tag['_id'] = BSON::ObjectId.new
      new_tag['module_app_id'] = @module_app.id
      new_tag['parent_id'] = parent_id 
      new_tag.save
      module_tag.update_attribute(:parent_id, new_tag.id) if set_parent
    end

    def clone_tag_from_default(default_tag)
      clone_tag(default_tag, default_tag.id)
    end

    def clone_tag_to_default(default_tag)
      clone_tag(default_tag, nil, true)
    end

    def merge_default_tags(name, tag_leases)
      parent = @module_app.module_tags.create(name_translations: name, is_default: true)
      lease_by_module_app_id = tag_leases.inject({}) do |sorted, parent|
        sorted = parent.children.inject(sorted) do |children, lease|
          module_app_id = lease.module_app_id.to_s
          if children[module_app_id]
            children[module_app_id] += [lease]
          else
            children[module_app_id] = [lease]
          end
          children
        end
        sorted
      end
      merge_duplicates_in_module(parent, lease_by_module_app_id)
      tag_leases.each(&:destroy)
      parent
    end

    def merge_duplicates_in_module(parent, lease_by_module_app_id)
      lease_by_module_app_id.each do |module_app_id, leases|
        if leases.count > 0
          taggings = leases.map { |l| l.tag.taggings }.flatten
          module_tag =  merge_tags(parent.name_translations, taggings, module_app_id, true)
          module_tag.update_attribute(:parent_id, parent.id)
          leases.each(&:destroy)
        else
          leases[0].update_attributes(name_translations: parent.name_translations, is_default: true, parent_id: parent.id) unless leases[0].is_default
        end
      end
    end

    def merge_tags(name, taggings, module_app_id, default=nil)
      module_app = ModuleApp.find(module_app_id)
      new_tag = module_app.module_tags.create(name_translations: name, module_app_id: module_app.id, is_default: default)
      taggings.each do |tagging|
        tagging.taggable.taggings.create(tag_id: new_tag.tag.id) unless tagging.taggable.taggings.detect{|t| t.tag_id.eql?(new_tag.tag.id)}
      end
      new_tag
    end

    def merge_with_default_tags(name, tag_leases)
      lease_by_module_app_id = tag_leases.inject({}) do |sorted, lease|
        module_app_id = lease.is_default ? 'default' : lease.module_app_id.to_s
        if sorted[module_app_id]
          sorted[module_app_id] += [lease]
        else
          sorted[module_app_id] = [lease]
        end
        sorted
      end
      if lease_by_module_app_id['default'].count > 1
        parent = merge_default_tags(name, lease_by_module_app_id['default'])
      else
        parent = lease_by_module_app_id['default'][0]
        parent.update_attributes(name_translations: name)
      end
      lease_by_module_app_id.delete('default')
      lease_by_module_app_id = parent.children.inject(lease_by_module_app_id) do |sorted, lease|
        module_app_id = lease.module_app_id.to_s
        if sorted[module_app_id]
          sorted[module_app_id] += [lease]
        else
          sorted[module_app_id] = [lease]
        end
        sorted
      end
      merge_duplicates_in_module(parent, lease_by_module_app_id)
    end

  end
  
end
