package ru.yandex.webmaster3.storage.turbo.service.css;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.databind.annotation.JsonTypeIdResolver;
import ru.yandex.webmaster3.core.util.json.polymorphic.DiscriminatorBasedTypeResolver;
import ru.yandex.webmaster3.core.util.json.polymorphic.Polymorphic;

import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
 * Created by Oleg Bazdyrev on 21/05/2018.
 */
@JsonTypeInfo(use = JsonTypeInfo.Id.CUSTOM,
        include = JsonTypeInfo.As.EXTERNAL_PROPERTY,
        property = "type")
@JsonTypeIdResolver(DiscriminatorBasedTypeResolver.class)
@JsonIgnoreProperties(ignoreUnknown = true)
public abstract class TurboCssError implements Polymorphic<TurboCssErrorType> {

    public List<TurboCssErrorInfo> toInfoList() {
        return Collections.singletonList(new TurboCssErrorInfo(getType(), null, null, null, null));
    }

    @JsonIgnoreProperties(ignoreUnknown = true)
    public static final class EmptyCssError extends TurboCssError {

        @Override
        public TurboCssErrorType getType() {
            return TurboCssErrorType.EMPTY_CSS;
        }
    }

    @JsonIgnoreProperties(ignoreUnknown = true)
    public static final class CssTooBigError extends TurboCssError {

        @Override
        public TurboCssErrorType getType() {
            return TurboCssErrorType.CSS_TOO_BIG;
        }
    }

    @JsonIgnoreProperties(ignoreUnknown = true)
    public static final class PostCssError extends TurboCssError {

        private final PostCssErrorData data;

        @JsonCreator
        public PostCssError(PostCssErrorData data) {
            this.data = data;
        }

        public PostCssErrorData getData() {
            return data;
        }

        @Override
        public TurboCssErrorType getType() {
            return TurboCssErrorType.POSTCSS;
        }

        @Override
        public List<TurboCssErrorInfo> toInfoList() {
            return Collections.singletonList(new TurboCssErrorInfo(getType(), data.getLine(), data.getColumn(), null, data.getMessage()));
        }
    }

    @JsonIgnoreProperties(ignoreUnknown = true)
    public static final class PostCssErrorData {

        private final Integer line;
        private final Integer column;
        private final String source;
        private final String message;

        @JsonCreator
        public PostCssErrorData(Integer line, Integer column, String source, String message) {
            this.line = line;
            this.column = column;
            this.source = source;
            this.message = message;
        }

        public Integer getLine() {
            return line;
        }

        public Integer getColumn() {
            return column;
        }

        public String getSource() {
            return source;
        }

        public String getMessage() {
            return message;
        }
    }

    @JsonIgnoreProperties(ignoreUnknown = true)
    public static final class StyleLintError extends TurboCssError {

        private final StyleLintErrorData data;

        @JsonCreator
        public StyleLintError(StyleLintErrorData data) {
            this.data = data;
        }

        public StyleLintErrorData getData() {
            return data;
        }

        @Override
        public TurboCssErrorType getType() {
            return TurboCssErrorType.STYLELINT;
        }

        @Override
        public List<TurboCssErrorInfo> toInfoList() {
            return data.warnings.stream()
                    .map(warning -> new TurboCssErrorInfo(getType(), warning.line, warning.column, warning.rule, warning.text))
                    .collect(Collectors.toList());
        }
    }

    @JsonIgnoreProperties(ignoreUnknown = true)
    public static final class StyleLintErrorData {

        private final List<StyleLintWarning> warnings;

        @JsonCreator
        public StyleLintErrorData(List<StyleLintWarning> warnings) {
            this.warnings = warnings;
        }

        public List<StyleLintWarning> getWarnings() {
            return warnings;
        }
    }

    @JsonIgnoreProperties(ignoreUnknown = true)
    public static final class StyleLintWarning {

        private final String text;
        private final String severity;
        private final String rule;
        private final Integer line;
        private final Integer column;

        @JsonCreator
        public StyleLintWarning(String text, String severity, String rule, Integer line, Integer column) {
            this.text = text;
            this.severity = severity;
            this.rule = rule;
            this.line = line;
            this.column = column;
        }

        public String getText() {
            return text;
        }

        public String getSeverity() {
            return severity;
        }

        public String getRule() {
            return rule;
        }

        public Integer getLine() {
            return line;
        }

        public Integer getColumn() {
            return column;
        }
    }

}
