package ru.yandex.autotests.directapi.darkside.datacontainers.jsonrpc.displaycanvas;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.gson.Gson;
import org.apache.commons.lang.RandomStringUtils;

import ru.yandex.autotests.directapi.darkside.exceptions.DarkSideException;
import ru.yandex.autotests.directapi.darkside.model.bslogs.BannerLanguage;
import ru.yandex.autotests.irt.testutils.RandomUtils;

/**
 * Created by pashkus on 07.09.16.
 * https://st.yandex-team.ru/TESTIRT-10191
 * <p>
 * Data model for json object "moderation_info" in ../DisplayCanvas/update_creatives request
 * Also using in db field ppc.perf_creatives.moderation_info
 */

public class ModerationInfo {

    @JsonProperty("html")
    public ModerationInfoHtml html;

    @JsonProperty("images")
    public List<ModerationInfoImage> images;

    @JsonProperty("texts")
    public List<ModerationInfoText> texts;

    @JsonProperty("sounds")
    public List<ModerationInfoSound> sounds;

    @JsonProperty("videos")
    public List<ModerationInfoVideo> videos;

    @JsonProperty("aspects")
    public List<ModerationInfoAspects> aspects;

    public static class ModerationInfoHtml {
        @JsonProperty("url")
        public String url;

        public String getUrl() {
            return url;
        }

        public ModerationInfoHtml setUrl(String url) {
            this.url = url;
            return this;
        }

        public ModerationInfoHtml() {
        }

        public ModerationInfoHtml generateTestData() {
            return this.setUrl("http://yandex.ru/" + RandomStringUtils.randomAlphanumeric(8));
        }
    }

    public static class ModerationInfoText {
        @JsonProperty("text")
        public String text;

        @JsonProperty("type")
        public String type;

        @JsonProperty("color")
        public String color;

        public String getText() {
            return text;
        }

        public String getType() {
            return type;
        }

        public String getColor() {
            return color;
        }

        public ModerationInfoText() {
        }

        public ModerationInfoText setText(String text) {
            this.text = text;
            return this;
        }

        public ModerationInfoText setType(String type) {
            this.type = type;
            return this;
        }

        public ModerationInfoText setColor(String color) {
            this.color = color;
            return this;
        }

        public ModerationInfoText generateTestData() {
            return generateTestData(BannerLanguage.ENGLISH);
        }

        public ModerationInfoText generateTestData(BannerLanguage textLang) {
            char[] chars;
            switch (textLang) {
                case RUSSIAN:
                    chars = RandomUtils.CYRILYC_CHARS;
                    break;
                case ENGLISH:
                    chars = RandomUtils.LATIN_CHARS;
                    break;
                case KAZAKH:
                    chars = RandomUtils.KAZAKH_CHARS;
                    break;
                case TURKISH:
                    chars = RandomUtils.TURKEY_CHARS;
                    break;
                case UKRAINIAN:
                    chars = RandomUtils.UKRAIN_CHARS;
                    break;
                case GERMAN:
                    chars = RandomUtils.GERMAN_CHARS;
                    break;
                case BELARUSIAN:
                    chars = RandomUtils.BELARUSIAN_CHARS;
                    break;
                case UZBEK:
                    chars = RandomUtils.UZBEK_CHARS;
                    break;
                default:
                    throw new DarkSideException("Unknown language: " + textLang.toString());
            }
            return this
                    .setText(RandomStringUtils.random(8, chars))
                    .setType("button")
                    .setColor("#" + RandomStringUtils.randomNumeric(6));
        }
    }

    public static class ModerationInfoImage {
        @JsonProperty("url")
        public String url;

        @JsonProperty("alt")
        public String alt;

        public String getUrl() {
            return url;
        }

        public String getAlt() {
            return alt;
        }

        public ModerationInfoImage() {
        }

        public ModerationInfoImage setUrl(String url) {
            this.url = url;
            return this;
        }

        public ModerationInfoImage setAlt(String alt) {
            this.alt = alt;
            return this;
        }

        public ModerationInfoImage generateTestData() {
            return this
                    .setUrl("http://testdata.ru/" + RandomStringUtils.randomAlphanumeric(6) + ".jpg")
                    .setAlt("alternative text " + RandomStringUtils.randomAlphanumeric(8));
        }
    }

    public static class ModerationInfoSound {
        public String url;
        public Long stockId;

        public String getUrl() {
            return url;
        }

        public Long getStockId() {
            return stockId;
        }

        public ModerationInfoSound setUrl(String url) {
            this.url = url;
            return this;
        }

        public ModerationInfoSound setStockId(Long stockId) {
            this.stockId = stockId;
            return this;
        }

        public ModerationInfoSound generateTestData() {
            return this
                    .setUrl("http://testdata.ru/" + RandomStringUtils.randomAlphanumeric(6) + ".mp3")
                    .setStockId((long) RandomUtils.getNextInt());
        }
    }

    public static class ModerationInfoVideo {
        public String url;
        public Long stockId;

        public String getUrl() {
            return url;
        }

        public Long getStockId() {
            return stockId;
        }

        public ModerationInfoVideo setUrl(String url) {
            this.url = url;
            return this;
        }

        public ModerationInfoVideo setStockId(Long stockId) {
            this.stockId = stockId;
            return this;
        }

        public ModerationInfoVideo generateTestData() {
            return this
                    .setUrl("http://testdata.ru/" + RandomStringUtils.randomAlphanumeric(6) + ".avi")
                    .setStockId((long) RandomUtils.getNextInt());
        }
    }

    public static class ModerationInfoAspects {
        public Integer width;
        public Integer height;

        public Integer getWidth() {
            return width;
        }

        public ModerationInfoAspects setWidth(Integer width) {
            this.width = width;
            return this;
        }

        public Integer getHeight() {
            return height;
        }

        public ModerationInfoAspects setHeight(Integer height) {
            this.height = height;
            return this;
        }

        public ModerationInfoAspects defaultAspect() {
            return this
                    .setWidth(15)
                    .setHeight(9);
        }
    }

    public ModerationInfoHtml getHtml() {
        return html;
    }

    public List<ModerationInfoImage> getImages() {
        return images;
    }

    public List<ModerationInfoText> getTexts() {
        return texts;
    }

    public ModerationInfo setHtml(ModerationInfoHtml html) {
        this.html = html;
        return this;
    }

    public ModerationInfo setImages(List<ModerationInfoImage> images) {
        this.images = images;
        return this;
    }

    public ModerationInfo setTexts(List<ModerationInfoText> texts) {
        this.texts = texts;
        return this;
    }

    public ModerationInfo setSounds(List<ModerationInfoSound> sounds) {
        this.sounds = sounds;
        return this;
    }

    public ModerationInfo setVideos(List<ModerationInfoVideo> videos) {
        this.videos = videos;
        return this;
    }

    public ModerationInfo setAspects(List<ModerationInfoAspects> aspects) {
        this.aspects = aspects;
        return this;
    }

    public List<ModerationInfoSound> getSounds() {
        return sounds;
    }

    public List<ModerationInfoVideo> getVideos() {
        return videos;
    }

    public List<ModerationInfoAspects> getAspects() {
        return aspects;
    }

    public ModerationInfo generateTestData() {
        return generateTestData(BannerLanguage.RUSSIAN);
    }

    public ModerationInfo generateTestData(BannerLanguage textLang) {
        return this
                .setHtml(new ModerationInfoHtml().generateTestData())
                .setImages(Arrays.asList(
                        new ModerationInfoImage().generateTestData(),
                        new ModerationInfoImage().generateTestData()))
                .setTexts(Arrays.asList(
                        new ModerationInfoText().generateTestData(textLang),
                        new ModerationInfoText().generateTestData(textLang)
                ));
    }

    public ModerationInfo generateTestDataWithVideoAddition() {
        return this
                .setHtml(new ModerationInfoHtml().generateTestData())
                .setVideos(Arrays.asList(
                        new ModerationInfoVideo().generateTestData(),
                        new ModerationInfoVideo().generateTestData()
                ))
                .setAspects(Arrays.asList(
                        new ModerationInfoAspects().defaultAspect()
                ));
    }

    /**
     * Добавляет элемент в массив texts.
     * Если массива ещё нет, он создаётся.
     * Помимо типа и текста ещё выставляет новому элементу дефолтный цвет.
     *
     * @param type значение type у нового элемента
     * @param value значение text у нового элемента
     * @return this
     */
    public ModerationInfo addText(String type, String value) {
        List<ModerationInfoText> modInfoTexts = this.getTexts();
        if (modInfoTexts == null) {
            modInfoTexts = Collections.emptyList();
        }
        List<ModerationInfoText> newTexts = new ArrayList<>(modInfoTexts);
        ModerationInfoText newText = new ModerationInfoText();
        newText.setType(type);
        newText.setText(value);
        newText.setColor("#FFFFFF");
        newTexts.add(newText);
        this.setTexts(newTexts);

        return this;
    }

    @Deprecated
    public String asJson() {
        return new Gson().toJson(this);
    }

    @Override
    public String toString() {
        return new Gson().toJson(this); //ToDo: use JsonUtils.gson_low_inline. make it public! Freedom! :)
    }

}

