package ru.yandex.qe.dispenser.domain;

import java.util.LinkedHashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import com.google.common.collect.HashBasedTable;
import com.google.common.collect.ImmutableMap;
import org.apache.commons.lang3.ArrayUtils;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.MessageSource;
import org.springframework.stereotype.Component;

import ru.yandex.qe.dispenser.api.v1.DiResourcePreorderReasonType;

@Component
public class GoalQuestionHelper {
    private static final Map<Long, String> REQUEST_GOAL_QUESTION_MESSAGE_KEY_BY_ID = ImmutableMap.<Long, String>builder()
            .put(0L, "question-if-one-time-or-yearly")
            .put(1L, "question-what-if-no")
            .put(2L, "question-what-if-half")
            .put(4L, "question-growth-reasons")
            .put(5L, "question-growth-moderation")
            .put(6L, "question-what-if-no-or-half")
            .build();

    private final MessageSource messageSource;
    private final MessageSource naturalGrowthMessageSource;

    private final List<RequestGoalQuestionId> requestGoalQuestionIds;
    private final HashBasedTable<DiResourcePreorderReasonType, Long, RequestGoalQuestionId> requestGoalIdCache;
    private final LinkedHashSet<Long> goalAnswerIds;
    private final LinkedHashSet<Long> growthAnswerIds;

    public GoalQuestionHelper(@Qualifier("messageSource") final MessageSource messageSource,
                              @Qualifier("naturalGrowthMessageSource") final MessageSource naturalGrowthMessageSource,
                              @Value("${request.goals.required.answers.goal}") final LinkedHashSet<Long> goalAnswerIds,
                              @Value("${request.goals.required.answers.growth}") final LinkedHashSet<Long> growthAnswerIds) {
        this.messageSource = messageSource;
        this.naturalGrowthMessageSource = naturalGrowthMessageSource;
        this.goalAnswerIds = goalAnswerIds;
        this.growthAnswerIds = growthAnswerIds;

        requestGoalIdCache = HashBasedTable.create();

        requestGoalQuestionIds = Stream.concat(
                goalAnswerIds.stream().map(id -> new RequestGoalQuestionId(id, DiResourcePreorderReasonType.GOAL)),
                growthAnswerIds.stream().map(id -> new RequestGoalQuestionId(id, DiResourcePreorderReasonType.GROWTH))
        )
                .peek(id -> requestGoalIdCache.put(id.getReasonType(), id.getId(), id))
                .collect(Collectors.toList());
    }

    public String getRequestGoalQuestion(final RequestGoalQuestionId questionId) {
        return getRequestGoalQuestion(questionId.getReasonType(), questionId.getId());
    }

    public String getRequestGoalQuestion(final DiResourcePreorderReasonType type, final Long questionId) {
        final MessageSource source = type == DiResourcePreorderReasonType.GOAL ? messageSource : naturalGrowthMessageSource;
        return source.getMessage(REQUEST_GOAL_QUESTION_MESSAGE_KEY_BY_ID.get(questionId), ArrayUtils.EMPTY_OBJECT_ARRAY, Locale.forLanguageTag("ru"));
    }

    public List<RequestGoalQuestionId> getRequestGoalQuestionIds() {
        return requestGoalQuestionIds;
    }

    public RequestGoalQuestionId getRequestGoalQuestionId(final DiResourcePreorderReasonType type, final Long questionId) {
        return requestGoalIdCache.get(type, questionId);
    }

    public LinkedHashSet<Long> getGoalAnswerIds() {
        return goalAnswerIds;
    }

    public LinkedHashSet<Long> getGrowthAnswerIds() {
        return growthAnswerIds;
    }

    public static class RequestGoalQuestionId {
        private final long id;
        private final DiResourcePreorderReasonType reasonType;

        private RequestGoalQuestionId(final long questionId, final DiResourcePreorderReasonType reasonType) {
            this.id = questionId;
            this.reasonType = reasonType;
        }

        public long getId() {
            return id;
        }

        public DiResourcePreorderReasonType getReasonType() {
            return reasonType;
        }

        @Override
        public boolean equals(final Object o) {
            if (this == o) {
                return true;
            }
            if (o == null || getClass() != o.getClass()) {
                return false;
            }
            final RequestGoalQuestionId that = (RequestGoalQuestionId) o;
            return id == that.id &&
                    reasonType == that.reasonType;
        }

        @Override
        public int hashCode() {
            return Objects.hash(id, reasonType);
        }

        @Override
        public String toString() {
            return reasonType + "-" + id;
        }
    }
}
