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

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.base.Charsets;
import com.google.common.base.Strings;
import org.apache.commons.collections4.CollectionUtils;
import ru.yandex.webmaster3.core.turbo.model.TurboUrl;
import ru.yandex.webmaster3.core.turbo.model.error.TurboRawError;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
 * Created by ifilippov5 on 06.06.18.
 */
public class TurboApiPagesRawStatsData {

    private final List<TurboApiPagesRawStatsData.Item> items;
    private final List<ObjectNode> errors;
    private final ObjectNode stats;
    private final String hash;

    @JsonCreator
    public TurboApiPagesRawStatsData(List<TurboApiPagesRawStatsData.Item> items, List<ObjectNode> errors, ObjectNode stats, String hash) {
        this.items = items == null ? Collections.emptyList() : items;
        this.errors = errors == null ? Collections.emptyList() : errors;
        this.stats = stats;
        this.hash = hash;
    }

    public List<TurboApiPagesRawStatsData.Item> getItems() {
        return items;
    }

    public List<ObjectNode> getErrors() {
        return errors;
    }

    public ObjectNode getStats() {
        return stats;
    }

    public String getHash() {
        return hash;
    }

    public boolean hasUrls() {
        return !CollectionUtils.isEmpty(items);
    }

    public boolean hasErrors() {
        return !CollectionUtils.isEmpty(errors);
    }

    public List<TurboUrl> collectTurboUrls(final String prefix, final boolean encode) {
        return items.stream()
                .filter(item -> !Strings.isNullOrEmpty(item.getPreview()) || item.isDeleted())
                .map(item -> item.toTurboUrl(prefix, encode))
                .collect(Collectors.toList());
    }

    public List<TurboRawError> collectTurboRawErrors() {
        List<TurboRawError> rawErrors = new ArrayList<>();
        for (ObjectNode error : errors) {
            rawErrors.add(TurboRawError.fromObjectNode(error, null));
        }
        for (TurboApiPagesRawStatsData.Item item : items) {
            for (ObjectNode error : item.getErrors()) {
                rawErrors.add(TurboRawError.fromObjectNode(error, item.getLink()));
            }
        }
        rawErrors.sort(TurboRawError.BY_CODE_AND_LINE);
        return rawErrors;
    }

    public static final class Item {

        private final String link;
        private final String title;
        private final String preview;
        private final String hash;
        private final boolean deleted;
        private final List<ObjectNode> errors;

        @JsonCreator
        public Item(@JsonProperty("link") String link,
                    @JsonProperty("title") String title,
                    @JsonProperty("preview") String preview,
                    @JsonProperty("hash") String hash,
                    @JsonProperty("is_deleted") boolean deleted,
                    @JsonProperty("errors") List<ObjectNode> errors) {
            this.link = link;
            this.title = title;
            this.preview = preview;
            this.hash = hash;
            this.deleted = deleted;
            this.errors = errors == null ? Collections.emptyList() : errors;
        }

        public String getLink() {
            return link;
        }

        public String getTitle() {
            return title;
        }

        public String getPreview() {
            return preview;
        }

        public boolean isDeleted() {
            return deleted;
        }

        public List<ObjectNode> getErrors() {
            return errors;
        }

        public TurboUrl toTurboUrl(String prefix, boolean encode) {
            String saasKey = preview;
            if (encode) {
                try {
                    saasKey = saasKey == null ? null : URLEncoder.encode(saasKey, Charsets.UTF_8.name());
                } catch (UnsupportedEncodingException e) {
                    throw new RuntimeException(e);
                }
            }
            return new TurboUrl(link, saasKey == null ? null : (prefix + saasKey), title, hash, deleted);
        }
    }
}
