class ProductCategory
  include SimplyStored::Couch
  include ActiveModel::SerializerSupport

  property :name
  property :position, type: Fixnum, default: 0
  property :full_day, type: :boolean, default: true
  property :start_from, type: Fixnum, default: 1320 # 22:00
  property :end_on, type: Fixnum, default: 1380 # 23:00
  property :active_on_sunday, type: :boolean, default: true
  property :active_on_monday, type: :boolean, default: true
  property :active_on_tuesday, type: :boolean, default: true
  property :active_on_wednesday, type: :boolean, default: true
  property :active_on_thursday, type: :boolean, default: true
  property :active_on_friday, type: :boolean, default: true
  property :active_on_saturday, type: :boolean, default: true

  belongs_to :supplier
  #has_and_belongs_to_many :products, storing_keys: true
  has_many :products

  attr_protected :supplier_id

  validates :name, presence: true
  validates :position, numericality: true
  validates :supplier_id, presence: true
  validates :end_on, numericality: {less_than: 2880}, presence: {unless: :full_day?}

  view :by_supplier_id_and_id, key: [:supplier_id, :_id]

  #TODO I am uuuuggggllyyyyy
  def self.for_user(user, options = {})
    table = options[:table]
    raise "ProductCategory.for_user requires a table" unless table.present?
    list = options[:list] || table.active_list # Performance option to specify it in stead of loading it
    supplier = options[:supplier] || table.supplier # same as list

    # Get supplier objects
    product_categories = for_supplier_in_time(supplier, options[:time])

    # The following part is creating the products hash. This should not be performed here!!!!!! #TODO fix this!!!@@!!@@!!@
    #products = supplier.products

    # Append other category if not defined by supplier
    #other = product_categories.find(&:other?) || (product_categories << self.other).last # Container for non categorized products

    # Initialize base return object
    h = {table_number: table.number, table_occupied: table.occupied?, supplier_name: supplier.name, my_list: list.try(:user_ids).to_a.include?(user.id)}

    #(products - product_categories.map(&:products).flatten).each{ |p| other.add_product(p) }
    h[:categories] = product_categories.map(&:to_client_format).select(&:present?)
    h
  end

  # time is not by default Time.now.utc since it can be specified as nil
  def self.for_supplier_in_time(supplier, time = nil)
    time ||= Time.now.in_time_zone(supplier.time_zone)
    minute = (time.seconds_since_midnight/60).round
    week_day = time.wday
    if minute < supplier.night_offset
      minute += 1440 # 1440 is 1 day in minutes 1.day/1.minute
      week_day -= 1
      week_day = 6 if week_day < 0 # Saturday
    end
    view_options = {reduce: false, include_docs: true}
    product_categories = database.view(by_supplier_id_and_week_time(view_options.merge(keys: [[supplier.id, week_day], [supplier.id, week_day, minute]])))
    product_categories.sort_by!{|pc| (pc.position || 90000).to_i }
    # sort categories
    product_categories
  end

  def active?(time = Time.now)
    return true unless time_zone = supplier.time_zone.presence # cannot do activity magic without the appropriate time zone

    true
  end

  def to_client_format
    return {} unless products.present?
    {name: name, products: products.to_a.map{|p| p.as_json}}
  end

  def other?
    %w[other overig].include?(name.to_s.downcase)
  end
  def self.other(options = {})
    new(options.reverse_merge(name: I18n.t('user.product_category.other_name')))
  end
end
