package ru.yandex.autotests.directapi.steps.statistics;

import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.stream.Collectors;

import org.apache.commons.io.IOUtils;

import ru.yandex.autotests.directapi.apiclient.RequestHeader;
import ru.yandex.autotests.directapi.apiclient.config.ConnectionConfig;
import ru.yandex.autotests.directapi.apiclient.errors.AxisError;
import ru.yandex.autotests.directapi.apiclient.methods.Method;
import ru.yandex.autotests.directapi.common.api45mng.NormalizedKeywordsData;
import ru.yandex.autotests.directapi.exceptions.DirectAPIException;
import ru.yandex.autotests.directapi.model.statistics.GetSummaryStatRequestMap;
import ru.yandex.autotests.directapi.model.statistics.KeywordIntersectionRequestMap;
import ru.yandex.autotests.directapi.model.statistics.KeywordsSuggestionInfoMap;
import ru.yandex.autotests.directapi.model.statistics.NewReportInfoMap;
import ru.yandex.autotests.directapi.model.statistics.RearrangeKeywordsRequestMap;
import ru.yandex.autotests.directapi.rules.Bin;
import ru.yandex.autotests.directapi.rules.Binable;
import ru.yandex.autotests.directapi.steps.BaseApiSteps;
import ru.yandex.autotests.irt.testutils.allure.LogSteps;
import ru.yandex.autotests.irt.testutils.json.JsonUtils;
import ru.yandex.qatools.allure.annotations.Step;

/**
 * Created with IntelliJ IDEA.
 * User: pavryabov
 * Date: 25.09.13
 * Time: 1:01
 * To change this template use File | Settings | File Templates.
 */
public class StatisticsSteps extends BaseApiSteps implements Binable<Integer> {
    private LogSteps log = LogSteps.getLogger(this.getClass());

    public static final String ADDITIONAL_RELEVANT_PHRASES_EN = "Automatically-added phrases";
    public static final String ADDITIONAL_RELEVANT_PHRASES_RU = "Автоматически добавленные фразы";
    public static final int GET_STAT_GOALS_ITEMS_LIMIT = 100;
    public static final int CAMPAIGN_WITH_SUMMARY_STAT = 9585813;
    public static final String CAMPAIGN_WITH_SUMMARY_STAT_START_DATE = "2018-03-01";
    public static final int CAMPAIGN_WITH_SUMMARY_STAT_LIMIT_TESTS = 3501044; //2011 - 2013


    public NewReportInfoMap newReportInfo;
    public static final int GET_KEYWORDS_SUGGESTION_COST_PER_WORD = 3;
    public GetSummaryStatRequestMap getSummaryStatRequest;

    private static StatisticsSteps _instance;

    public Bin<Integer> bin = new Bin(this);

    private StatisticsSteps(ConnectionConfig connectionConfig, RequestHeader requestHeader) {
        super(connectionConfig, requestHeader);
    }


    public static StatisticsSteps getInstance(ConnectionConfig connectionConfig, RequestHeader requestHeader) {
        if (_instance == null) {
            _instance = new StatisticsSteps(connectionConfig, requestHeader);
        } else {
            _instance.setConnectionConfig(connectionConfig);
            _instance.setRequestHeader(requestHeader);
        }
        _instance.reloadModels();
        return _instance;

    }

    private void reloadModels() {
        String packageName = connectionConfig.getPackage();
        getSummaryStatRequest = new GetSummaryStatRequestMap(packageName);
        newReportInfo = new NewReportInfoMap(packageName);
    }

    public Callable clearBin(final Set<Integer> binData) {
        return new Callable() {
            public Object call() throws Exception {
                Integer[] reportIDs = binData.toArray(new Integer[0]);
                for (int reportID : reportIDs) {
                    try {
                        deleteReport(reportID);
                    } catch (AxisError axisFault) {
                        log.info("Отчет не удалился");
                    }
                }
                return null;
            }
        };
    }

    @Step("[DeleteReport]: {0}")
    public void deleteReport(int reportID) {
        bin.removeFromBin(reportID);
        jsonClient().invokeMethod(Method.DELETE_REPORT, reportID);

    }

    public <T> T[] getBalance(Integer... campaignIDS) {
        return (T[]) jsonClient().invokeMethod(Method.GET_BALANCE, campaignIDS);
    }

    @Step("[GetStatGoals]: запрос списка целей")
    public <T> T[] getStatGoals(Object request) {
        return (T[]) jsonClient().invokeMethod(Method.GET_STAT_GOALS, request);
    }

    public String[] getKeywordSuggestion(KeywordsSuggestionInfoMap keywordsSuggestionInfoMap) {
        return jsonClient().invokeMethod(Method.GET_KEYWORDS_SUGGESTION, keywordsSuggestionInfoMap.getBean());
    }

    /**
     * Available for internal roles only
     *
     * @param keywordsSuggestionInfoMap
     * @return
     */
    public String[] getNormalizedKeywords(KeywordsSuggestionInfoMap keywordsSuggestionInfoMap) {
        return jsonClient().invokeMethod(Method.GET_NORMALIZED_KEYWORDS, keywordsSuggestionInfoMap.getBean());
    }

    /**
     * Available for internal roles only
     *
     * @param keywordsSuggestionInfoMap
     * @return
     */
    public NormalizedKeywordsData[][] getNormalizedKeywordsData(KeywordsSuggestionInfoMap keywordsSuggestionInfoMap) {
        return jsonClient().invokeMethod(Method.GET_NORMALIZED_KEYWORDS_DATA, keywordsSuggestionInfoMap.getBean());
    }

    public <T> T getKeywordsIntersection(KeywordIntersectionRequestMap keywordsIntersection) {
        return jsonClient().invokeMethod(Method.GET_KEYWORDS_INTERSECTION, keywordsIntersection.getBean());
    }

    public <T> T rearrangeKeywords(RearrangeKeywordsRequestMap rearrangeKeywordsRequestMap) {
        return jsonClient().invokeMethod(Method.REARRANGE_KEYWORDS, rearrangeKeywordsRequestMap.getBean());
    }

    //endregion

    public static List<String> readFile(URL file) {
        List<String> testData = new ArrayList<>();
        try {
            InputStream in = file.openStream();
            try {
                testData = IOUtils.readLines(in);
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                IOUtils.closeQuietly(in);
            }
        } catch (IOException e) {
            throw new DirectAPIException("Ошибка чтения файла " + file.getFile());
        }
        return testData;
    }

    public static <NewReportInfo> List<NewReportInfo> parseRequests(String source, Class newReportInfo) {
        List<String> testData;
        URL fileURL;
        try {
            if (source.startsWith("https")) {
                fileURL = new URL(source);
            } else {
                throw new MalformedURLException();
            }
        } catch (MalformedURLException e) {
            throw new DirectAPIException("Неверный формат пути к файлу " + source);
        }
        testData = readFile(fileURL);
        List<NewReportInfo> requests =
                testData.stream()
                        .map(x -> (NewReportInfo) JsonUtils.getObject(x, newReportInfo))
                        .collect(Collectors.toList());
        return requests;
    }

    public static String overrideProperty(String property, String propertyName) {
        String systemPropertyValue = System.getProperties().getProperty(propertyName);
        return (systemPropertyValue != null) ? systemPropertyValue : property;
    }
}
