# encoding: UTF-8
#
# Copyright (c) 2010-2017 GoodData Corporation. All rights reserved.
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree.

require 'gooddata'

ROW_BASED_DATA = [
  ['tomas@gooddata.com', 'US', 'CZ', 'KZ'],
  ['petr@gooddata.com', 'US'],
  ['petr@gooddata.com', 'KZ']
]
COLUMN_BASED_DATA_WITH_HEADERS = [
  {
    :login => 'tomas@gooddata.com',
    :country => 'US',
    :age => 14
  },
  {
    :login => 'petr@gooddata.com',
    :country => 'US',
    :age => 19
  },
  {
    :login => 'petr@gooddata.com',
    :country => 'KZ',
    :age => 30
  }
]

COLUMN_BASED_DATA_WITH_HEADERS_AND_NIL_VAL = [
  {
    :login => 'tomas@gooddata.com',
    :country => 'US',
    :age => 14
  },
  {
    :login => 'petr@gooddata.com',
    :country => 'US',
    :age => 19
  },
  {
    :login => 'petr@gooddata.com',
    :country => 'KZ',
    :age => nil
  }
]

COLUMN_BASED_DATA_WITH_HEADERS_AND_EMPTY_VAL = [
  {
    :login => 'tomas@gooddata.com',
    :country => 'US',
    :age => 14
  },
  {
    :login => 'petr@gooddata.com',
    :country => 'US',
    :age => 19
  },
  {
    :login => 'petr@gooddata.com',
    :country => 'KZ',
    :age => ''
  }
]

describe "DSL" do
  it "should pick the values from row based file" do
    results = GoodData::UserFilterBuilder.get_values(ROW_BASED_DATA, :labels => [{ :label => "label/34" }])
    expect(results).to eq({
      "tomas@gooddata.com" => [
        { :label => "label/34", :values => %w(US CZ KZ), :over => nil, :to => nil }
      ],
     "petr@gooddata.com" => [
       { :label => "label/34", :values => ["US"], :over => nil, :to => nil },
       { :label => "label/34", :values => ["KZ"], :over => nil, :to => nil }
      ]
    })
  end

  it "should pick the values from column based file" do
    results = GoodData::UserFilterBuilder.get_values(
      COLUMN_BASED_DATA_WITH_HEADERS,
      :type => :filter,
      :user_column => :login,
      :labels => [{ :label => "label/34", :column => :country }]
    )
    expect(results).to eq({
      "tomas@gooddata.com" => [
        { :label => "label/34", :values => ["US"], :over => nil, :to => nil }
      ],
     "petr@gooddata.com" => [
       { :label => "label/34", :values => ["US"], :over => nil, :to => nil },
       { :label => "label/34", :values => ["KZ"], :over => nil, :to => nil }
      ]
    })
  end

  it "should pick the values from column based file with multiple columns" do
    results = GoodData::UserFilterBuilder.get_values(
      COLUMN_BASED_DATA_WITH_HEADERS,
      :type => :filter,
      :user_column => :login,
      :labels => [{ :label => "label/34", :column => :country }, { :label => "label/99", :column => :age }]
    )
    expect(results).to eq({
      "tomas@gooddata.com" => [
        { :label => "label/34", :values => ["US"], :over => nil, :to => nil },
        { :label => "label/99", :values => [14], :over => nil, :to => nil }
      ],
     "petr@gooddata.com" => [
       { :label => "label/34", :values => ["US"], :over => nil, :to => nil },
       { :label => "label/99", :values => [19], :over => nil, :to => nil },
       { :label => "label/34", :values => ["KZ"], :over => nil, :to => nil },
       { :label => "label/99", :values => [30], :over => nil, :to => nil }
      ]
    })
  end

  it "should process end to end" do
    results = GoodData::UserFilterBuilder.get_filters(
      COLUMN_BASED_DATA_WITH_HEADERS,
      :user_column => :login,
      :labels => [{ :label => { :uri => "label/34" }, :column => :country }, { :label => { :uri => "label/99" }, :column => :age }]
    )
    expect(results).to eq [
      {
        :login => "tomas@gooddata.com",
        :filters => [
          { :label => { :uri => "label/34" }, :values => ["US"], :over => nil, :to => nil },
          { :label => { :uri => "label/99" }, :values => [14], :over => nil, :to => nil }
        ]
      },
      {
        :login => "petr@gooddata.com",
        :filters => [
          { :label => { :uri => "label/34" }, :values => %w(US KZ), :over => nil, :to => nil },
          { :label => { :uri => "label/99" }, :values => [19, 30], :over => nil, :to => nil }
        ]
      }
    ]
  end

  it "should process end to end nil value should be ignored" do
    results = GoodData::UserFilterBuilder.get_filters(
      COLUMN_BASED_DATA_WITH_HEADERS_AND_NIL_VAL,
      :user_column => :login,
      :labels => [{ :label => { :uri => "label/34" }, :column => :country }, { :label => { :uri => "label/99" }, :column => :age }]
    )
    expect(results).to eq [
      {
        :login => "tomas@gooddata.com",
        :filters => [
          { :label => { :uri => "label/34" }, :values => ["US"], :over => nil, :to => nil },
          { :label => { :uri => "label/99" }, :values => [14], :over => nil, :to => nil }
        ]
      },
      {
        :login => "petr@gooddata.com",
        :filters => [
          { :label => { :uri => "label/34" }, :values => %w(US KZ), :over => nil, :to => nil },
          { :label => { :uri => "label/99" }, :values => [19], :over => nil, :to => nil }
        ]
      }
    ]
  end

  it "should process end to end nil value should be ignored" do
    results = GoodData::UserFilterBuilder.get_filters(
      COLUMN_BASED_DATA_WITH_HEADERS_AND_EMPTY_VAL,
      :user_column => :login,
      :labels => [
        { :label => { :uri => "label/34" }, :column => :country },
        { :label => { :uri => "label/99" }, :column => :age }
      ]
    )
    expect(results).to eq [
      {
        :login => "tomas@gooddata.com",
        :filters => [
          { :label => { :uri => "label/34" }, :values => ["US"], :over => nil, :to => nil },
          { :label => { :uri => "label/99" }, :values => [14], :over => nil, :to => nil }
        ]
      },
      {
        :login => "petr@gooddata.com",
        :filters => [
          { :label => { :uri => "label/34" }, :values => %w(US KZ), :over => nil, :to => nil },
          { :label => { :uri => "label/99" }, :values => [19, ""], :over => nil, :to => nil }
        ]
      }
    ]
  end

  it "should collect values for every user" do
    data = {
      "tomas" => [
        { :label => "label/34", :values => ["US"] },
        { :label => "label/34", :values => ["KZ"] },
        { :label => "label/99", :values => [18] },
        { :label => "label/99", :values => [20] }
      ],
      "petr" => [
        { :label => "label/34", :values => ["US"] },
        { :label => "label/99", :values => [2] },
        { :label => "label/99", :values => [1] }
      ]
    }
    results = GoodData::UserFilterBuilder.reduce_results(data)
    expect(results).to eq [
      {
        :login => "tomas",
        :filters => [
          { :label => "label/34", :values => %w(US KZ), :over => nil, :to => nil },
          { :label => "label/99", :values => [18, 20], :over => nil, :to => nil }
        ]
      },
      {
        :login => "petr",
        :filters => [
          { :label => "label/34", :values => ["US"], :over => nil, :to => nil },
          { :label => "label/99", :values => [2, 1], :over => nil, :to => nil }
        ]
      }
    ]
  end

  it "should collect values for every label" do
    data = [
      { :label => "label/34", :values => ["US"] },
      { :label => "label/34", :values => ["KZ"] },
      { :label => "label/99", :values => [18] },
      { :label => "label/99", :values => [20] }
    ]
    results = GoodData::UserFilterBuilder.collect_labels(data)
    expect(results).to eq [
      { :label => "label/34", :values => %w(US KZ), :over => nil, :to => nil },
      { :label => "label/99", :values => [18, 20], :over => nil, :to => nil }
    ]
  end

  it "should collect values" do
    data = [
      { :label => "label/34", :values => ["US"] },
      { :label => "label/34", :values => ["KZ"] }
    ]
    results = GoodData::UserFilterBuilder.collect_values(data)
    expect(results).to eq %w(US KZ)
  end

  it "should translate filters into MAQL filters" do
    data = [
      {
        :login => "tomas@gooddata.com",
        :filters => [
          { :label => "label/34", :values => ["US"] },
          { :label => "label/99", :values => [14] }
        ]
      },
      {
        :login => "petr@gooddata.com",
        :filters => [
          { :label => "label/34", :values => %w(US KZ) },
          { :label => "label/99", :values => [19] }
        ]
      }
    ]
    results = data.map do |user_data|
      {
        :login => user_data[:login],
        :maql_filter => user_data[:filters].map { |item| "[#{item[:label]}] IN (#{item[:values].join(', ')})" }.join(" AND ")
      }
    end
    expect(results).to eq [
      { :login => "tomas@gooddata.com", :maql_filter => "[label/34] IN (US) AND [label/99] IN (14)" },
      { :login => "petr@gooddata.com", :maql_filter => "[label/34] IN (US, KZ) AND [label/99] IN (19)" }
    ]
  end
end
