package ru.yandex.direct.api.v5.security;

import java.util.Optional;

import javax.annotation.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;

import com.google.common.collect.ImmutableSet;

import ru.yandex.direct.core.entity.user.model.ApiUser;

import static com.google.common.base.Preconditions.checkState;

/**
 * Представление промежуточных данных об аутентификации. Может не содержать данные о целевом пользователе
 * запроса {@code subjectUser}, если его не удалось определить. Нужно в случае, если требуется получить данные
 * об аутентификации до окончательной аутентификации/авторизации, например, в фильтрах, для логирования и т.п.
 * Если все данные об аутентифицации известны {@code isFullyAuthorized() == true}, то это промежуточное представление
 * можно преобразовать в конечное, с помощью {@code toDirectApiAuthentication()}
 */
@ParametersAreNonnullByDefault
public class DirectApiPreAuthentication {

    private static final String ANDROID_MOBILE_APP_APPLICATION_ID = "74a699cdfe004d6ca576cfe4a8bfd79a";

    private static final ImmutableSet<String> MOBILE_APPS_APPLICATION_IDS = ImmutableSet.of(
            "389dfb36ef1f4a16a2cdb47bc4510c7f",
            "a4286bedd73840fb966a41277ffcbf40",
            "74a699cdfe004d6ca576cfe4a8bfd79a");

    private final DirectApiCredentials directApiCredentials;
    /**
     * Идентификатор приложения
     */
    private final String applicationId;
    private final ApiUser operator;
    private final ApiUser chiefOperator;
    private final String tvmUserTicket;

    @Nullable
    private final ApiUser subjectUser;
    @Nullable
    private final ApiUser chiefSubjectUser;

    public DirectApiPreAuthentication(DirectApiCredentials directApiCredentials, String applicationId,
                                      ApiUser operator, ApiUser chiefOperator,
                                      @Nullable ApiUser subjectUser,
                                      @Nullable ApiUser chiefSubjectUser) {
        this(directApiCredentials, applicationId, operator, chiefOperator, null, subjectUser, chiefSubjectUser);
    }

    public DirectApiPreAuthentication(DirectApiCredentials directApiCredentials, String applicationId,
                                      ApiUser operator, ApiUser chiefOperator,
                                      @Nullable String tvmUserTicket,
                                      @Nullable ApiUser subjectUser,
                                      @Nullable ApiUser chiefSubjectUser) {
        this.directApiCredentials = directApiCredentials;
        this.applicationId = applicationId;
        this.operator = operator;
        this.chiefOperator = chiefOperator;
        this.tvmUserTicket = tvmUserTicket;
        this.subjectUser = subjectUser;
        this.chiefSubjectUser = chiefSubjectUser;
    }

    public DirectApiCredentials getDirectApiCredentials() {
        return directApiCredentials;
    }

    public String getApplicationId() {
        return applicationId;
    }

    public boolean isMobileApplication() {
        return MOBILE_APPS_APPLICATION_IDS.contains(applicationId);
    }

    public boolean isAndroidMobileApplication() {
        return ANDROID_MOBILE_APP_APPLICATION_ID.equals(applicationId);
    }

    public ApiUser getOperator() {
        return operator;
    }

    public ApiUser getChiefOperator() {
        return chiefOperator;
    }

    public Optional<ApiUser> getSubjectUser() {
        return Optional.ofNullable(subjectUser);
    }

    public Optional<ApiUser> getChiefSubjectUser() {
        return Optional.ofNullable(chiefSubjectUser);
    }

    public boolean isFullyAuthorized() {
        return subjectUser != null && chiefSubjectUser != null;
    }

    public String getTvmUserTicket() {
        return tvmUserTicket;
    }

    /**
     * Преобразовать в конечное представление объекта аутентификации
     */
    public DirectApiAuthentication toDirectApiAuthentication() {
        checkState(isFullyAuthorized());
        //noinspection ConstantConditions
        return new DirectApiAuthentication(operator, chiefOperator, subjectUser, chiefSubjectUser,
                directApiCredentials.getClientLogin() == null, tvmUserTicket, applicationId,
                directApiCredentials.getUserIp());
    }
}
