package ru.yandex.webmaster3.viewer.http.sitemap.analyze.model;

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

import lombok.Getter;

import ru.yandex.webmaster3.core.data.HttpResponsePart;
import ru.yandex.webmaster3.core.http.ActionResponse;
import ru.yandex.webmaster3.core.sitemap.SitemapErrorCode;
import ru.yandex.webmaster3.storage.sitemap.SitemapTypeEnum;
import ru.yandex.webmaster3.storage.sitemap.service.model.AnalyzeSitemapErrorType;
import ru.yandex.webmaster3.storage.util.SitemapAnalysisResult;
import ru.yandex.webmaster3.viewer.http.async.model.BaseAsyncInfoErrorType;

/**
 * @author: ishalaru
 * DATE: 16.05.2019
 */
public abstract class AnalyzeSitemapInfoResponse implements ActionResponse {

    @Getter
    public static class NormalResponse extends AnalyzeSitemapInfoResponse implements ActionResponse.NormalResponse {
        private final Integer urlCount;

        private final List<SitemapError> errors;
        private final List<SitemapError> warnings;

        private final Integer shownErrorsCount;
        private final Integer totalErrorsCount;
        private final Integer shownWarningsCount;
        private final Integer totalWarningsCount;

        private final Long sitemapFileSize;
        private final String sitemapFileName;

        private final SitemapTypeEnum sitemapType;
        private final boolean inProgress;

        public NormalResponse(final SitemapAnalysisResult result,
                              final long sitemapFileSize, final String sitemapFileName) {
            this.urlCount = result.getUrlCount();
            this.totalWarningsCount = result.getTotalWarningsCount();
            if (result.getTotalErrorsCount() != null && result.getTotalWarningsCount() != null) {
                this.totalErrorsCount = result.getTotalErrorsCount() - result.getTotalWarningsCount();
            } else {
                this.totalErrorsCount = result.getTotalErrorsCount();
            }

            this.errors = new ArrayList<>();
            this.warnings = new ArrayList<>();
            for (SitemapAnalysisResult.SitemapErrorInfo info : result.getErrorInfos()) {
                SitemapErrorCode sitemapErrorCode = info.getCode();
                // WMC-91 temporary fix
                Integer lineNumber = info.getLineNumber() != null && info.getLineNumber() < 65535 ? info.getLineNumber() : null;
                final SitemapError e = new SitemapError(sitemapErrorCode, lineNumber, info.getMessage());
                if (sitemapErrorCode.isError()) {
                    errors.add(e);
                } else {
                    warnings.add(e);
                }
            }
            this.shownErrorsCount = errors.size();
            this.shownWarningsCount = warnings.size();

            this.sitemapFileSize = sitemapFileSize;
            this.sitemapFileName = sitemapFileName;

            this.sitemapType = result.getSitemapType();
            this.inProgress = false;
        }

        public NormalResponse(boolean inProgress) {
            this.urlCount = null;
            this.errors = null;
            this.warnings = null;
            this.shownErrorsCount = null;
            this.totalErrorsCount = null;
            this.shownWarningsCount = null;
            this.totalWarningsCount = null;
            this.sitemapFileSize = null;
            this.sitemapFileName = null;
            this.sitemapType = null;
            this.inProgress = inProgress;
        }

        public static AnalyzeSitemapInfoResponse.NormalResponse stillInProgress() {
            return new AnalyzeSitemapInfoResponse.NormalResponse(true);
        }
    }

    public static class SitemapError {
        private final SitemapErrorCode code;
        private final Integer lineNumber;
        private final String message;

        public SitemapError(SitemapErrorCode code, Integer lineNumber, String message) {
            this.code = code;
            this.lineNumber = lineNumber;
            this.message = message;
        }

        public SitemapErrorCode getCode() {
            return code;
        }

        public Integer getLineNumber() {
            return lineNumber;
        }

        public String getMessage() {
            return message;
        }
    }


    static abstract class BaseErrorResponse extends AnalyzeSitemapInfoResponse implements ActionResponse.ErrorResponse {
        private final Class<?> clazz;
        protected BaseErrorResponse(Class<?> clazz) {this.clazz = clazz;}
        @Override public Class<?> getClazz() {return clazz;}
    }

    public static class IllegalHttpCodeResponse extends AnalyzeSitemapInfoResponse.BaseErrorResponse {
        private final HttpResponsePart httpResponse;

        public IllegalHttpCodeResponse(Class<?> clazz, HttpResponsePart httpResponse) {
            super(clazz);
            this.httpResponse = httpResponse;
        }

        @Override public Enum<?> getCode() {return AnalyzeSitemapErrorType.ANALYZE_SITEMAP__ILLEGAL_HTTP_CODE;}
        @Override public String getMessage() {return AnalyzeSitemapErrorType.ANALYZE_SITEMAP__ILLEGAL_HTTP_CODE.getErrorDescription();}
        public HttpResponsePart getHttpResponse() {return httpResponse;}
    }

    public static class SitemapAnalyzeErrorResponse extends AnalyzeSitemapInfoResponse.BaseErrorResponse {
        private final AnalyzeSitemapErrorType analyzeSitemapErrorType;


        public SitemapAnalyzeErrorResponse(Class<?> clazz, AnalyzeSitemapErrorType analyzeSitemapErrorType) {
            super(clazz);
            this.analyzeSitemapErrorType = analyzeSitemapErrorType;
        }

        @Override public Enum<?> getCode() {return analyzeSitemapErrorType;}
        @Override public String getMessage() {return analyzeSitemapErrorType.getErrorDescription();}
    }

    public static class SitemapAnalyzeIsEmptyResponse extends AnalyzeSitemapInfoResponse.SitemapAnalyzeErrorResponse {
        private final HttpResponsePart httpResponse;

        public SitemapAnalyzeIsEmptyResponse(Class<?> clazz, AnalyzeSitemapErrorType analyzeSitemapErrorType, HttpResponsePart httpResponse) {
            super(clazz,analyzeSitemapErrorType);
            this.httpResponse = httpResponse;
        }

        public HttpResponsePart getHttpResponse() {return httpResponse;}
    }

    public static class RequestIdNotFound extends AnalyzeSitemapInfoResponse.BaseErrorResponse {
        public RequestIdNotFound(Class<?> clazz) {super(clazz);}
        @Override public Enum<?> getCode() {return BaseAsyncInfoErrorType.BASE_ASYNC_INFO__REQUEST_NOT_FOUND;}
        @Override public String getMessage() {return  BaseAsyncInfoErrorType.BASE_ASYNC_INFO__REQUEST_NOT_FOUND.getErrorDescription();}
    }

    @Deprecated
    public static class RequestStillInProgress extends AnalyzeSitemapInfoResponse.BaseErrorResponse {
        public RequestStillInProgress(Class<?> clazz) {super(clazz);}
        @Override public Enum<?> getCode() {return  BaseAsyncInfoErrorType.BASE_ASYNC_INFO__REQUEST_STILL_IN_PROGRESS;}
        @Override public String getMessage() {return  BaseAsyncInfoErrorType.BASE_ASYNC_INFO__REQUEST_STILL_IN_PROGRESS.getErrorDescription();}
    }

    public static class RequestFailed extends AnalyzeSitemapInfoResponse.BaseErrorResponse {
        public RequestFailed(Class<?> clazz) {super(clazz);}
        @Override public Enum<?> getCode() {return  BaseAsyncInfoErrorType.BASE_ASYNC_INFO__REQUEST_FAILED;}
        @Override public String getMessage() {return  BaseAsyncInfoErrorType.BASE_ASYNC_INFO__REQUEST_FAILED.getErrorDescription();}
    }

    public static class ResponseDataCorrupted extends AnalyzeSitemapInfoResponse.BaseErrorResponse{
        public ResponseDataCorrupted(Class<?> clazz) {super(clazz);}
        @Override public Enum<?> getCode() {return  BaseAsyncInfoErrorType.BASE_ASYNC_INFO__DATA_CORRUPTED;}
        @Override public String getMessage() {return  BaseAsyncInfoErrorType.BASE_ASYNC_INFO__DATA_CORRUPTED.getErrorDescription();}
    }


    public static class SitemapIsTooLongResponse extends AnalyzeSitemapInfoResponse.BaseErrorResponse {
        public SitemapIsTooLongResponse(Class<?> clazz) {super(clazz);}
        @Override public Enum<?> getCode() {return AnalyzeSitemapErrorType.ANALYZE_SITEMAP__SITEMAP_IS_TOO_LONG;}
        @Override public String getMessage() {return AnalyzeSitemapErrorType.ANALYZE_SITEMAP__SITEMAP_IS_TOO_LONG.getErrorDescription();}
    }

    public static class SitemapIsHomepageResponse extends AnalyzeSitemapInfoResponse.BaseErrorResponse {
        public SitemapIsHomepageResponse(Class<?> clazz) {super(clazz);}
        @Override public Enum<?> getCode() {return AnalyzeSitemapErrorType.ANALYZE_SITEMAP__SITEMAP_IS_HOMEPAGE;}
        @Override public String getMessage() {return AnalyzeSitemapErrorType.ANALYZE_SITEMAP__SITEMAP_IS_HOMEPAGE.getErrorDescription();}
    }

    public static class UnableToDownloadSitemapResponse extends AnalyzeSitemapInfoResponse.BaseErrorResponse {
        public UnableToDownloadSitemapResponse(Class<?> clazz) {super(clazz);}
        @Override public Enum<?> getCode() {return AnalyzeSitemapErrorType.ANALYZE_SITEMAP__UNABLE_TO_DOWNLOAD_SITEMAP;}
        @Override public String getMessage() {return AnalyzeSitemapErrorType.ANALYZE_SITEMAP__UNABLE_TO_DOWNLOAD_SITEMAP.getErrorDescription();}
    }

    public static class SitemapIsForbiddenInRobotsTxtResponse extends AnalyzeSitemapInfoResponse.BaseErrorResponse {
        public SitemapIsForbiddenInRobotsTxtResponse(Class<?> clazz) {super(clazz);}
        @Override public Enum<?> getCode() {return AnalyzeSitemapErrorType.ANALYZE_SITEMAP__SITEMAP_FORBIDDEN_IN_ROBOTS_TXT;}
        @Override public String getMessage() {return AnalyzeSitemapErrorType.ANALYZE_SITEMAP__SITEMAP_FORBIDDEN_IN_ROBOTS_TXT.getErrorDescription();}
    }


}
