require_relative '../parser/configuration-file'
require_relative 'section'
require_relative 'setting'

module SDDMConfigurationEditor
  class Configuration
    def find_counterparts(array1, array2, key, &block)
      array1.each do |item1|
        found = array2.find do |item2|
          item2[key].to_sym == item1[key].to_sym
        end
        yield [item1, found]
      end
    end

    attr_reader :model
    def initialize(schema, config_file)
      load_schema(schema)
      parse_values(config_file)
    end

    def load_schema(schema)
      @model = schema

      # Replace the setting hashes with Setting objects
      @model.each do |section|
        settings = section[:settings]
        settings.map! do |setting_data|
          setting_data[:value] = ''
          Setting.new(setting_data)
        end
      end

      @model.map! do |section_data|
        Section.new(section_data)
      end
      @model
    end

    def parse_values(config_file)
      config_values = ConfigurationFileParser.new.parse(config_file)
      # Merge values into schema
      find_counterparts(@model, config_values, :name) do
        |(schema_section, value_section)|
        if value_section
          value_settings = value_section[:settings]
          schema_settings = schema_section.settings
          find_counterparts(schema_settings, value_settings, :key) do
            |schema_setting, value_setting|
            if value_setting
              schema_setting.value = value_setting[:value]
            else
              schema_setting.value = ''
            end
          end
        end
      end
      @model
    end

    def generate_file
      ''.tap do |content|
        content << "# Generated by SDDM Configuration Editor\n"
        @model.each do |section|
          changed_settings = section.settings.select do |setting|
            setting.isDefined
          end
          unless changed_settings.empty?
            content << "[#{section.name}]\n"
            changed_settings.each do |setting|
              content << "#{setting.key}=#{setting.value}\n"
            end
            content << "\n"
          end
        end
      end
    end
  end
end

