package ru.yandex.qe.dispenser.api.v1;

import java.io.IOException;
import java.util.Collections;
import java.util.List;
import java.util.Objects;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import org.jetbrains.annotations.NotNull;

import ru.yandex.qe.dispenser.api.util.JsonDeserializerBase;
import ru.yandex.qe.dispenser.api.util.SerializationUtils;

@JsonDeserialize(using = DiBotSyncStatus.Deserializer.class)
public class DiBotSyncStatus {

    private final DiBotSyncStatus.Status status;
    private final String date;
    private final List<String> errors;

    private DiBotSyncStatus(final Builder builder) {
        this.status = builder.status;
        this.date = builder.date;
        this.errors = builder.errors != null
                ? Collections.unmodifiableList(builder.errors)
                : Collections.emptyList();
    }

    public Status getStatus() {
        return status;
    }

    public String getDate() {
        return date;
    }

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

    public static Builder builder() {
        return new Builder();
    }

    @Override
    public boolean equals(final Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        final DiBotSyncStatus that = (DiBotSyncStatus) o;
        return status == that.status &&
                Objects.equals(date, that.date) &&
                Objects.equals(errors, that.errors);
    }

    @Override
    public int hashCode() {
        return Objects.hash(status, date, errors);
    }

    @Override
    public String toString() {
        return "DiBotSyncStatus{" +
                "status=" + status +
                ", date=" + date +
                ", errors=" + errors +
                '}';
    }

    public enum  Status {
        SUCCESS,
        FAIL,
    }

    public static class Builder {
        private Status status;
        private String date;
        private List<String> errors;

        public Builder status(final Status status) {
            this.status = status;
            return this;
        }

        public Builder date(final String date) {
            this.date = date;
            return this;
        }

        public Builder errors(final List<String> errors) {
            this.errors = errors;
            return this;
        }

        public DiBotSyncStatus build() {
            return new DiBotSyncStatus(this);
        }
    }

    static final class Deserializer extends JsonDeserializerBase<DiBotSyncStatus> {

        private final static TypeReference<List<String>> LIST_STRING_REFERENCE = new TypeReference<List<String>>() {};

        @NotNull
        @Override
        public DiBotSyncStatus deserialize(final @NotNull JsonParser jp, final @NotNull DeserializationContext dc) throws IOException {
            final JsonNode json = toJson(jp);

            final JsonNode status = json.get("status");
            final JsonNode date = json.get("date");
            final JsonNode errors = json.get("errors");

            return builder()
                    .status(!status.isNull() ? SerializationUtils.convertValue(status, DiBotSyncStatus.Status.class) : null)
                    .date(!date.isNull() ? date.asText() : null)
                    .errors(!errors.isNull() ? SerializationUtils.convertValue(errors, LIST_STRING_REFERENCE) : null)
                    .build();
        }
    }
}
