require 'base64'
require_relative '../wendelin_client'
require_relative '../dataset_utils'

module Embulk
  module Output

    class Wendelin < OutputPlugin
      Plugin.register_output("wendelin", self)

      def self.transaction(config, schema, count, &control)
	task = {
	  "erp5_url" => config.param("erp5_url", :string),
	  "path_prefix" => config.param("path_prefix", :string,  :default => nil),
	  "type_input" => config.param("type_input", :string,  :default => nil),
	  "data_set" => config.param("data_set", :string, default: nil),
	  "erp5_base_url" => config.param("erp5_base_url", :string, default: nil),
	  "tool_dir" => config.param('tool_dir', :string)
	}
	storage_ingestion = ! task["type_input"]
	@logger = LogManager.instance()
	@dataset_utils = DatasetUtils.new(Dir.pwd)
	task["user"], task["password"] = @dataset_utils.getCredentials(task["tool_dir"])
	if storage_ingestion
	  @wendelin = WendelinClient.new(task["erp5_base_url"], task["user"], task["password"])
	  @new_dataset_description = @dataset_utils.datasetDescriptionPendingFileExist(task["data_set"], task["tool_dir"])
	  @dataset_utils.setDatasetDescription(task["data_set"], task["tool_dir"], @wendelin) if @new_dataset_description
	end
	task_reports = yield(task)
	next_config_diff = {}
	if task_reports.length > 0
	  @logger.info("Your ingested files will be available in the site in a few minutes. Thank for your patience.", print=TRUE)
	  if storage_ingestion
	    done_tasks = task_reports.map{|hash| hash[DatasetUtils::RUN_DONE]}.flatten.compact
	    @dataset_utils.showTaskReport(done_tasks)
	    @logger.info("#{done_tasks.length} new file(s) ingested.", print=TRUE)
	    if(done_tasks.length == count)
	      @logger.info("Dataset successfully ingested.", print=TRUE)
	      @wendelin = WendelinClient.new(task["erp5_base_url"], task["user"], task["password"])
	      @wendelin.increaseDatasetVersion(task["data_set"])
	    else
	      failed_tasks = task_reports.map{|hash| hash[DatasetUtils::RUN_ERROR] || hash[DatasetUtils::RUN_ABORTED] }.flatten.compact
	      @dataset_utils.showTaskErrors(failed_tasks, storage=TRUE)
	    end
	  end
	else
	  @logger.info("No new files found for ingestion.", print=TRUE)
	  if storage_ingestion
	    @logger.info("You can restart the ingestion from this storage by running your command again with parameter --restart .", print=TRUE)
	  end
	end
	return next_config_diff
      end

      def init
	credentials = {}
	@erp5_url = task["erp5_url"]
	@logger = LogManager.instance()
	@wendelin = WendelinClient.new(@erp5_url, task["user"], task["password"])
      end

      def add(page)
	page.each do |record|
	  @return_value = DatasetUtils::RUN_ERROR
	  supplier = (record[0].nil? || record[0].empty?) ? "default" : record[0]
	  dataset = (record[1].nil? || record[1].empty?) ? "default" : record[1]
	  filename = record[2]
	  extension = record[3]
	  eof = record[5]
	  data_chunk = record[4]
	  size = record[6]
	  hash = record[7]
	  begin
	    if eof == DatasetUtils::DELETE
	      @reference = [dataset, filename, extension].join(DatasetUtils::REFERENCE_SEPARATOR)
	      @wendelin.delete(@reference)
	    elsif eof == DatasetUtils::RENAME
	      @reference = [dataset, filename, extension].join(DatasetUtils::REFERENCE_SEPARATOR)
	      @wendelin.rename(@reference, record[4].to_s)
	    else
	      @reference = [supplier, dataset, filename, extension, eof, size, hash].join(DatasetUtils::REFERENCE_SEPARATOR)
	      split = eof != ""
	      ingestion_response = @wendelin.ingest(@reference, data_chunk, split)
	      if not ingestion_response["success"]
		raise ingestion_response["message"]
	      end
	    end
	  rescue Exception => e
	    @logger.error(e.backtrace)
	    raise e
	  end
	  @return_value = DatasetUtils::RUN_DONE
	end
      end

      def close
      end

      def finish
      end

      def abort
      end

      def commit
	task_report = {@return_value => @reference}
	return task_report
      end
    end

  end
end
