module Ads
  class Setting < Ads::Base
    include Code::Justin::Tv::Ads::Siosa::Proto
    attributes :ad_server_default, :force_client_ads, :force_server_ads, :guarantee_ads, :pbyp_disabled, :channel_id, :frequency, :max_ad_break_length, :prerolls_disabled, :postrolls_disabled, :required_age, :turbo_disabled, :vod_ads_enabled, :vod_archive_midrolls, :vod_archive_midrolls_frequency, :vod_archive_midrolls_break_length, :costreamers, :campaign_type
    self.primary_attribute = :channel_id

    def self.twirp_client
      @twirp_client ||= SiosaClient.new(connection)
    end

    def self.find(id)
      response = twirp_client.get_channel_ad_properties(ChannelId.new(channel_id: id.to_s), headers: {"User-Id": id.to_s})

      return nil if response.error

      from_attributes(convert_siosa_response(response))
    end

    def save
      id = self.attributes[:channel_id]
      # currently writing to two services, the Saul write will be removed very soon
      update_params = filtered_params

      unless update_params.empty?
        save_to_siosa(update_params, id)
      end
      true
    end

    def save_to_siosa(params, channel_id)
      input = convert_to_input(params)

      response = Setting.twirp_client.set_channel_ad_properties(input, headers: {"User-Id": channel_id.to_s})

      raise response.error.msg if response.error

      true
    end

    def filtered_params
      current = Setting.find(channel_id)
      self.attributes.except(:channel_id).select {|k, v| v.to_s != current.send(k).to_s}
    end

    def convert_to_input(params)
      set_properties = SetChannelAdPropertiesInput.new(
        channel_id: self.channel_id
      )

      property_list = []
      params.each do |k, v|
        ad_property = AdProperty.new
        ad_property.send("#{k}=", get_field_type(k, v))

        property_list.push(ad_property)
      end

      set_properties.input.replace(property_list)
      set_properties
    end

    def get_field_type(field_name, field)
      case field_name
      when "force_client_ads", "force_server_ads", "guarantee_ads", "pbyp_disabled", "prerolls_disabled", "postrolls_disabled", "turbo_disabled", "vod_ads_enabled"
        field == "true"
      when "required_age"
        field.to_i
      else
        field
      end
    end

    def self.convert_siosa_response(resp)
      ret_val = {}
      count_map = {}

      ret_val[:channel_id] = resp.data.channel_id
      prop_list = resp.data.valid_responses.properties

      props = [
        :ad_server_default,
        :force_client_ads,
        :force_server_ads,
        :guarantee_ads,
        :pbyp_disabled,
        :frequency,
        :max_ad_break_length,
        :prerolls_disabled,
        :postrolls_disabled,
        :required_age,
        :turbo_disabled,
        :vod_ads_enabled,
        :vod_archive_midrolls,
        :vod_archive_midrolls_frequency,
        :vod_archive_midrolls_break_length,
        :campaign_type
      ]

      props.each do |prop|
        val_map = {}
        count_map[prop] = val_map
        prop_list.each do |p|
          prop_val = p.send(prop)
          if val_map[prop_val]
            val_map[prop_val] += 1
          else
            val_map[prop_val] = 1
          end
        end
      end

      count_map.each do |k, v|
        if v.length == 1
          val, count = v.first
          ret_val[k] = val
        else
          v.each do |value, value_count|
            if value_count == 1
              ret_val[k] = value
            end
          end
        end
      end

      ret_val
    end
  end
end
