# encoding: utf-8
require "yaml" # persistence

module LogStash module PluginMixins
  class ValueTracking

    def self.build_last_value_tracker(plugin)
      if plugin.use_column_value && plugin.tracking_column_type == "numeric"
        # use this irrespective of the jdbc_default_timezone setting
        klass = NumericValueTracker
      else
        if plugin.jdbc_default_timezone.nil? || plugin.jdbc_default_timezone.empty?
          # no TZ stuff for Sequel, use Time
          klass = TimeValueTracker
        else
          # Sequel does timezone handling on DateTime only
          klass = DateTimeValueTracker
        end
      end

      handler = NullFileHandler.new(plugin.last_run_metadata_path)
      if plugin.record_last_run
        handler = FileHandler.new(plugin.last_run_metadata_path)
      end
      if plugin.clean_run
        handler.clean
      end

      instance = klass.new(handler)
    end

    attr_reader :value

    def initialize(handler)
      @file_handler = handler
      set_value(get_initial)
    end

    def get_initial
      # override in subclass
    end

    def set_value(value)
      # override in subclass
    end

    def write
      @file_handler.write(@value)
    end
  end


  class NumericValueTracker < ValueTracking
    def get_initial
      @file_handler.read || 0
    end

    def set_value(value)
      return unless value.is_a?(Numeric)
      @value = value
    end
  end

  class DateTimeValueTracker < ValueTracking
    def get_initial
      @file_handler.read || DateTime.new(1970)
    end

    def set_value(value)
      if value.respond_to?(:to_datetime)
        @value = value.to_datetime
      else
        @value = DateTime.parse(value)
      end
    end
  end

  class TimeValueTracker < ValueTracking
    def get_initial
      @file_handler.read || Time.at(0).utc
    end

    def set_value(value)
      if value.respond_to?(:to_time)
        @value = value.to_time
      else
        @value = DateTime.parse(value).to_time
      end
    end
  end

  class FileHandler
    def initialize(path)
      @path = path
      @exists = ::File.exist?(@path)
    end

    def clean
      return unless @exists
      ::File.delete(@path)
      @exists = false
    end

    def read
      return unless @exists
      YAML.load(::File.read(@path))
    end

    def write(value)
      ::File.write(@path, YAML.dump(value))
      @exists = true
    end
  end

  class NullFileHandler
    def initialize(path)
    end

    def clean
    end

    def read
    end

    def write(value)
    end
  end
end end
