# encoding: utf-8

# Copyright (c) [2018] SUSE LLC
#
# All Rights Reserved.
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of version 2 of the GNU General Public License as published
# by the Free Software Foundation.
#
# This program 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 this program; if not, contact SUSE LLC.
#
# To contact SUSE LLC about this file by physical or electronic mail, you may
# find current contact information at www.suse.com.

require "yast"
require "abstract_method"
require "y2storage/proposal/settings_adjustment"

module Y2Storage
  module Proposal
    module SettingsGenerator
      # Base class for a settings generator used to perform the initial proposal
      #
      # Derived classes must implement #calculate_next_settings method.
      #
      # @see InitialGuidedProposal
      class Base
        include Yast::Logger

        # Constructor
        #
        # A copy of the given settings is internally stored.
        #
        # @param settings [ProposalSettings] base settings
        def initialize(settings)
          initialize_settings(settings)
          initialize_adjustments(settings)
        end

        # This attribute contains information about any adjustment done to the settings
        #
        # @return [Proposal::SettingsAdjustment, nil] nil if the settings uses the legacy format
        attr_reader :adjustments

        # Next settings generated from the current version of the settings. The new settings are
        # generated by disabling some of its properties. A copy of the stored {#settings} is returned.
        #
        # @see #calculate_next_settings
        #
        # @return [ProposalSettings, nil] nil if nothing else can be disabled in the current settings
        def next_settings
          initial_settings || calculate_next_settings
        end

      private

        # Calculates the next settings to use after the initial settings
        #
        # @return [ProposalSettings]
        abstract_method :calculate_next_settings

        # Current settings
        #
        # This settings are used to calculate the next settings
        #
        # @return [ProposalSettings]
        attr_reader :settings

        # Sets the initial settings value
        #
        # @param settings [ProposalSettings]
        def initialize_settings(settings)
          @settings = Yast.deep_copy(settings)
        end

        # Sets the initial adjustments
        #
        # @param settings [ProposalSettings]
        def initialize_adjustments(settings)
          @adjustments = SettingsAdjustment.new if settings.ng_format?
        end

        # Settings to use for first time
        #
        # The first time that {#next_settings} is called, a copy of the original settings
        # is returned.
        #
        # @return [ProposalSettings]
        def initial_settings
          return nil if @used_initial_settings
          @used_initial_settings = true

          copy_settings
        end

        # Copies current settings
        #
        # @return [ProposalSettings]
        def copy_settings
          Yast.deep_copy(settings)
        end
      end
    end
  end
end
