# This file is a part of Redmine CRM (redmine_contacts) plugin,
# customer relationship management plugin for Redmine
#
# Copyright (C) 2010-2018 RedmineUP
# http://www.redmineup.com/
#
# redmine_contacts is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# redmine_contacts is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with redmine_contacts.  If not, see <http://www.gnu.org/licenses/>.

module CSVImportable
  class << self; attr_accessor :klass end

  def persisted?
    false
  end

  def initialize(attributes = {})
    attributes.each{|name, value| send("#{name}=", value)}
  end

  def save
    if imported_instances.any? && imported_instances.map(&:valid?).all? && imported_instances.map{|c| c.new_record? ? true : (c.respond_to?('editable?') ? c.editable? : true)}.all?
      begin
        klass.transaction do
          imported_instances.each(&:save!)
        end
      rescue
        Rails.logger.info $!.message
        Rails.logger.info $!.backtrace.join("\n")
        return false
      end
      true
    else
      imported_instances.each_with_index do |instance, index|
        if !instance.new_record? && !instance.editable?
          errors.add :base, "Row #{index + 2}: Permission restricted for changing #{klass.name}"
        else
          instance.errors.full_messages.each do |message|
            errors.add :base, "Row #{index + 2}: #{message}"
          end
        end
      end
      false
    end
  end

  def imported_instances
    @imported_instances ||= load_imported_instances
  end

protected
  def force_utf8(v)
    if v.respond_to? :force_encoding then v.force_encoding('utf-8') else v end
  end

private
  def build_custom_fields
    custom_fields_attributes = {}
    klass.new.custom_field_values.each do |custom_field_value|
      custom_fields_attributes[custom_field_value.custom_field.id.to_s] = custom_field_value.custom_field.cast_value(row[custom_field_value.custom_field.name]).to_s
    end
    custom_fields_attributes
  end

  def load_imported_instances
    instance_rows = open_import_source
    klass.transaction do
      begin
        line_counter = 0
        instance_rows.map do |row|
          line_counter += 1
          instance = klass.find_by_id(row['#']) || klass.new
          instance.attributes = build_from_fcsv_row(row)
          if instance.respond_to?(:custom_field_values)
            instance.custom_field_values.each do |custom_field_value|
              custom_field_value.value = custom_field_value.custom_field.cast_value(row[custom_field_value.custom_field.name.underscore]).to_s
            end
          end

          instance.project = project if instance.respond_to?(:project=)
          puts instance.errors.full_messages unless instance.valid?
          instance
        end
      rescue
        Rails.logger.info $!.message
        Rails.logger.info $!.backtrace.join("\n")
        errors.add :base, I18n.t(:text_crm_error_on_line, :line => line_counter, :error => $!.message)
        []
      end
    end
  end

  def open_import_source
    begin
      content = file.read
      FCSV.parse(content, :headers => true, :header_converters => [:downcase], :encoding => 'utf-8', :col_sep => guess_separator(force_utf8(content)), :quote_char => quotes_type)
    rescue Exception => e
      Rails.logger.info $!.message
      Rails.logger.info $!.backtrace.join("\n")
      errors.add :base, e.message
      []
    end
  end

  def guess_separator(content)
    first_line = content.split("\n").first
    commas = first_line.count(",")
    semicolons = first_line.count(";")
    commas > semicolons ? ',' : ';'
  end
end
