# frozen_string_literal:true

require_relative 'log'
require_relative 'exception'
require_relative 'sheep_obj'
require_relative 'node_buf'

module SheepAst
  # This object is base object of the sheep fuctory pattern
  # Factory abstract/wrap instanciation process and it absorb change impact inside the framework
  module FactoryBase
    include Log
    include Exception

    attr_reader :root_node
    attr_accessor :my_name
    attr_accessor :my_factory
    attr_accessor :ctime
    attr_accessor :match_factory
    attr_accessor :action_factory
    attr_accessor :data_store

    def initialize
      @ctime = Time.new
      @id_store = []
      @name_hash = {}
      @current_id = -1
      super()
    end

    def inspect
      "custom inspect <#{self.class.name} object_id = #{object_id}, my_name = #{@my_name}>"
    end

    def create_id(obj, name = nil)
      @current_id += 1
      @id_store.push obj
      obj.my_id = @current_id

      unless name.nil?
        bind_name(name, @current_id)
      end

      return @current_id
    end

    def from_id(id)
      ids = @id_store[id]
      return ids
    end

    def from_name(name)
      id = @name_hash[name]
      application_error "specified name = '#{name}' does not exist" if id.nil?

      return from_id(id)
    end

    def name_defined?(name)
      return true if @name_hash.key?(name)

      return false
    end

    def bind_name(name, id)
      if @name_hash.key?(name)
        application_error "same name is already registered '#{name}'"
      end

      @name_hash[name] = id
    end

    def get_factory(name)
      @factories.each do |fac|
        if fac.my_name == name
          return fac
        end
      end
      application_error 'factory not found'
    end
  end
end
