package ru.yandex.webmaster3.core.proto.converter;

import org.apache.commons.lang3.StringUtils;
import org.joda.time.Duration;
import org.joda.time.Instant;
import ru.yandex.webmaster3.core.searchquery.QueryFilter;
import ru.yandex.webmaster3.core.searchquery.QueryGroup;
import ru.yandex.webmaster3.core.searchquery.QueryIndicator;
import ru.yandex.webmaster3.core.searchquery.SpecialGroup;
import ru.yandex.webmaster3.proto.querygroups.Querygroups;

import java.util.ArrayList;
import java.util.List;

/**
 * @author avhaliullin
 */
public class QueryGroupConverter {
    public static Querygroups.HostGroupInfo queryGroup2Proto(QueryGroup group, List<String> queries) {
        Querygroups.HostGroupInfo.Builder builder = Querygroups.HostGroupInfo.newBuilder();

        if (group.getFilters() != null && !group.getFilters().isEmpty()) {
            Querygroups.FilterExpression expression;
            if (group.getFilters().size() == 1) {
                expression = filter2Proto(group.getFilters().get(0));
            } else {
                Querygroups.FilterExpression.Builder exprBuilder = Querygroups.FilterExpression.newBuilder();
                exprBuilder.setType(Querygroups.FilterExpressionType.AND);
                for (QueryFilter filter : group.getFilters()) {
                    exprBuilder.addFilterExpressions(filter2Proto(filter));
                }
                expression = exprBuilder.build();
            }
            builder.setFilterExpression(expression);
        }
        for (String query : queries) {
            builder.addQueries(query2Proto(query));
        }
        builder.setFavorite(group.getSpecialGroup() == SpecialGroup.SELECTED_QUERIES);
        Instant createDate = group.getCreateDate();
        if (createDate == null) {
            createDate = Instant.now().minus(Duration.standardDays(1));
        }
        builder.setCreationTimestamp(ConverterUtils.fromDateTime(createDate));
        return builder.build();
    }

    private static Querygroups.QueryInfo query2Proto(String query) {
        return Querygroups.QueryInfo.newBuilder().setText(query).build();
    }

    private static Querygroups.FilterExpression filter2Proto(QueryFilter filter) {
        if (filter.getOperation() == QueryFilter.Operation.TEXT_CONTAINS) {
            String text = filter.getText() == null ? "" : filter.getText();
            String[] split = StringUtils.split(text, '|');
            List<String> orFilter = new ArrayList<>();
            for (String s : split) {
                String filterPart = StringUtils.trimToEmpty(s);
                if (!filterPart.isEmpty()) {
                    orFilter.add(filterPart);
                }
            }
            if (orFilter.isEmpty()){
                return filter2ProtoInt(filter.withText(""));
            } else {
                Querygroups.FilterExpression.Builder exprBuilder = Querygroups.FilterExpression.newBuilder();
                exprBuilder.setType(Querygroups.FilterExpressionType.OR);
                for (String part : orFilter) {
                    exprBuilder.addFilterExpressions(filter2ProtoInt(filter.withText(part)));
                }
                return exprBuilder.build();
            }
        } else {
            return filter2ProtoInt(filter);
        }
    }

    private static Querygroups.FilterExpression filter2ProtoInt(QueryFilter filter) {
        Querygroups.QueryFilter.Builder builder = Querygroups.QueryFilter.newBuilder();
        fillIndicator(filter.getIndicator(), builder);
        fillOperation(filter, builder);

        Querygroups.FilterExpression.Builder exprBuilder = Querygroups.FilterExpression.newBuilder();
        exprBuilder.setType(Querygroups.FilterExpressionType.FILTER);
        exprBuilder.setFilter(builder.build());
        return exprBuilder.build();
    }

    private static void fillOperation(QueryFilter filter, Querygroups.QueryFilter.Builder builder) {
        float numValShiftShift = filter.getIndicator().isPosition() ? -1.0f : 0.0f;
        switch (filter.getOperation()) {
            case GREATER_EQUAL:
                builder.setType(Querygroups.QueryFilterType.GREATER_OR_EQUAL);
                builder.setFilterValue(filter.getNumberValue() + numValShiftShift);
                break;
            case GREATER_THAN:
                builder.setType(Querygroups.QueryFilterType.GREATER_THAN);
                builder.setFilterValue(filter.getNumberValue() + numValShiftShift);
                break;
            case LESS_EQUAL:
                builder.setType(Querygroups.QueryFilterType.LESS_OR_EQUAL);
                builder.setFilterValue(filter.getNumberValue() + numValShiftShift);
                break;
            case LESS_THAN:
                builder.setType(Querygroups.QueryFilterType.LESS_THAN);
                builder.setFilterValue(filter.getNumberValue() + numValShiftShift);
                break;
            case TEXT_CONTAINS:
                builder.setType(Querygroups.QueryFilterType.MATCHES_REGEXP);
                builder.setFilterText(filter.getText());//see https://st.yandex-team.ru/WMC-3225#1490655227000
                break;
            default:
                throw new IllegalArgumentException("Unsupported filter operation " + filter.getOperation());
        }
    }

    private static void fillIndicator(QueryIndicator indicator, Querygroups.QueryFilter.Builder builder) {
        switch (indicator) {
            case AVERAGE_CLICK_POSITION:
                builder.setIndicator(Querygroups.QueryIndicator.AVERAGE_CLICK_POSITION);
                break;
            case AVERAGE_CLICK_POSITION_2_3:
                builder.setIndicator(Querygroups.QueryIndicator.AVERAGE_CLICK_POSITION);
                builder.setIndicatorFromPosition(2);
                builder.setIndicatorUntilPosition(4);
                break;
            case AVERAGE_CLICK_POSITION_4_10:
                builder.setIndicator(Querygroups.QueryIndicator.AVERAGE_CLICK_POSITION);
                builder.setIndicatorFromPosition(4);
                builder.setIndicatorUntilPosition(11);
                break;
            case AVERAGE_CLICK_POSITION_11_50:
                builder.setIndicator(Querygroups.QueryIndicator.AVERAGE_CLICK_POSITION);
                builder.setIndicatorFromPosition(11);
                builder.setIndicatorUntilPosition(51);
                break;

            case AVERAGE_SHOW_POSITION:
                builder.setIndicator(Querygroups.QueryIndicator.AVERAGE_SHOW_POSITION);
                break;
            case AVERAGE_SHOW_POSITION_2_3:
                builder.setIndicator(Querygroups.QueryIndicator.AVERAGE_SHOW_POSITION);
                builder.setIndicatorFromPosition(2);
                builder.setIndicatorUntilPosition(4);
                break;
            case AVERAGE_SHOW_POSITION_4_10:
                builder.setIndicator(Querygroups.QueryIndicator.AVERAGE_SHOW_POSITION);
                builder.setIndicatorFromPosition(4);
                builder.setIndicatorUntilPosition(11);
                break;
            case AVERAGE_SHOW_POSITION_11_50:
                builder.setIndicator(Querygroups.QueryIndicator.AVERAGE_SHOW_POSITION);
                builder.setIndicatorFromPosition(11);
                builder.setIndicatorUntilPosition(51);
                break;

            case TOTAL_CLICKS_COUNT:
                builder.setIndicator(Querygroups.QueryIndicator.CLICKS_COUNT);
                break;
            case CLICKS_1_50:
                builder.setIndicator(Querygroups.QueryIndicator.CLICKS_COUNT);
                builder.setIndicatorFromPosition(1);
                builder.setIndicatorUntilPosition(51);
                break;
            case CLICKS_COUNT_1:
                builder.setIndicator(Querygroups.QueryIndicator.CLICKS_COUNT);
                builder.setIndicatorFromPosition(1);
                builder.setIndicatorUntilPosition(2);
                break;
            case CLICKS_COUNT_2_3:
                builder.setIndicator(Querygroups.QueryIndicator.CLICKS_COUNT);
                builder.setIndicatorFromPosition(2);
                builder.setIndicatorUntilPosition(4);
                break;
            case CLICKS_COUNT_4_10:
                builder.setIndicator(Querygroups.QueryIndicator.CLICKS_COUNT);
                builder.setIndicatorFromPosition(4);
                builder.setIndicatorUntilPosition(11);
                break;
            case CLICKS_COUNT_11_50:
                builder.setIndicator(Querygroups.QueryIndicator.CLICKS_COUNT);
                builder.setIndicatorFromPosition(11);
                builder.setIndicatorUntilPosition(51);
                break;

            case TOTAL_CTR:
                builder.setIndicator(Querygroups.QueryIndicator.CTR);
                break;
            case CTR_1:
                builder.setIndicator(Querygroups.QueryIndicator.CTR);
                builder.setIndicatorFromPosition(1);
                builder.setIndicatorUntilPosition(2);
                break;
            case CTR_2_3:
                builder.setIndicator(Querygroups.QueryIndicator.CTR);
                builder.setIndicatorFromPosition(2);
                builder.setIndicatorUntilPosition(4);
                break;
            case CTR_4_10:
                builder.setIndicator(Querygroups.QueryIndicator.CTR);
                builder.setIndicatorFromPosition(4);
                builder.setIndicatorUntilPosition(11);
                break;
            case CTR_11_50:
                builder.setIndicator(Querygroups.QueryIndicator.CTR);
                builder.setIndicatorFromPosition(11);
                builder.setIndicatorUntilPosition(51);
                break;

            case TOTAL_SHOWS_COUNT:
                builder.setIndicator(Querygroups.QueryIndicator.SHOWS_COUNT);
                break;
            case SHOWS_1_50:
                builder.setIndicator(Querygroups.QueryIndicator.SHOWS_COUNT);
                builder.setIndicatorFromPosition(1);
                builder.setIndicatorUntilPosition(51);
                break;
            case SHOWS_COUNT_1:
                builder.setIndicator(Querygroups.QueryIndicator.SHOWS_COUNT);
                builder.setIndicatorFromPosition(1);
                builder.setIndicatorUntilPosition(2);
                break;
            case SHOWS_COUNT_2_3:
                builder.setIndicator(Querygroups.QueryIndicator.SHOWS_COUNT);
                builder.setIndicatorFromPosition(2);
                builder.setIndicatorUntilPosition(4);
                break;
            case SHOWS_COUNT_4_10:
                builder.setIndicator(Querygroups.QueryIndicator.SHOWS_COUNT);
                builder.setIndicatorFromPosition(4);
                builder.setIndicatorUntilPosition(11);
                break;
            case SHOWS_COUNT_11_50:
                builder.setIndicator(Querygroups.QueryIndicator.SHOWS_COUNT);
                builder.setIndicatorFromPosition(11);
                builder.setIndicatorUntilPosition(51);
                break;

            case QUERY:
                builder.setIndicator(Querygroups.QueryIndicator.QUERY);
                break;
            case URL:
                builder.setIndicator(Querygroups.QueryIndicator.URL);
                break;
            default:
                throw new IllegalArgumentException("Unsupported indicator " + indicator);
        }
    }
}
