package ru.yandex.autotests.directapi.model.banners;

import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang.RandomStringUtils;

import ru.yandex.autotests.direct.utils.PhraseTexts;
import ru.yandex.autotests.direct.utils.converter.BeanMapToBeanConverter;
import ru.yandex.autotests.direct.utils.model.ModelBeanMap;
import ru.yandex.autotests.directapi.model.banners.phrases.BannerPhraseInfoMap;
import ru.yandex.autotests.irt.testutils.RandomUtils;
import ru.yandex.autotests.irt.testutils.json.JsonUtils;

import static ch.lambdaj.Lambda.convert;

/**
 * Created with IntelliJ IDEA.
 * User: mariabye
 * Date: 24.06.13
 * Time: 22:09
 * To change this template use File | Settings | File Templates.
 */
public class BannerInfoMap<T> extends ModelBeanMap<BannerInfoMap> {

    public static final int CREATE_BANNER_COST = 12;
    public static final int UPDATE_BANNER_COST = 4;
    public static final int CREATE_PHRASE_COST = 2;
    public static final int UPDATE_PHRASE_COST = 1;
    public static final int MAX_KEYWORD_LENGTH = 4096;
    public static final int MAX_HREF_LENGTH = 1024;

    //region Fields
    private static final String BANNER_INFO = "BannerInfo";
    public static final String BANNER_ID = "bannerID";
    public static final String CAMPAIGN_ID = "campaignID";
    public static final String TYPE = "type";
    public static final String TITLE = "title";
    public static final String TEXT = "text";
    public static final String HREF = "href";
    public static final String DOMAIN = "domain";
    public static final String CONTACT_INFO = "contactInfo";
    public static final String GEO = "geo";
    public static final String PHRASES = "phrases";
    public static final String MINUS_KEYWORDS = "minusKeywords";
    public static final String STATUS_ACTIVATING = "statusActivating";
    public static final String STATUS_ARCHIVE = "statusArchive";
    public static final String STATUS_BANNER_MODERATE = "statusBannerModerate";
    public static final String STATUS_PHRASES_MODERATE = "statusPhrasesModerate";
    public static final String STATUS_PHONE_MODERATE = "statusPhoneModerate";
    public static final String STATUS_SHOW = "statusShow";
    public static final String IS_ACTIVE = "isActive";
    public static final String STATUS_SITELINKS_MODERATE = "statusSitelinksModerate";
    public static final String SITELINKS = "sitelinks";
    public static final String AD_WARNINGS = "adWarnings";
    public static final String FIXED_ON_MODERATION = "fixedOnModeration";
    public static final String MODERATE_REJECTION_REASONS = "moderateRejectionReasons";
    public static final String AD_GROUP_ID = "adGroupID";
    public static final String AD_GROUP_NAME = "adGroupName";
    public static final String AUTO_MINUS_WORDS = "autoMinusWords";
    public static final String AGE_LABEL = "ageLabel";
    public static final String AD_IMAGE_HASH = "adImageHash";
    public static final String STATUS_AD_IMAGE_MODERATE = "statusAdImageModerate";
    public static final String AD_GROUP_MOBILE_BID_ADJUSTMENT = "adGroupMobileBidAdjustment";


    public static final String AD_GROUP_NAME_TEMPLATE = "Группа №%s";

    public static final int MOSCOW_METRO_COUNT = 179;
    public static final int SPB_METRO_COUNT = 62;
    public static final Integer[] METRO_REGIONS = new Integer[]{1, 2, 143};
    public static final int KIEV_METRO_COUNT = 50;
    public static final String MOSCOW = "Москва";
    public static final String SAINTPETERSBURG = "Санкт-Петербург";
    public static final Integer MOSCOW_METRO_ID = 20388;
    public static final Integer MIN_ADGROUP_MOBILE_BID_ADJUSTMENT = 50;
    public static final Integer MAX_ADGROUP_MOBILE_BID_ADJUSTMENT = 1300;

    //endregion


    public BannerInfoMap(String packageName) {
        super(packageName, BANNER_INFO);
    }

    public BannerInfoMap(T bannerInfo) {
        super();
        setBean(bannerInfo);
    }

    public BannerInfoMap put(String fieldName, Object value) {
        super.put((fieldName), value);
        return this;
    }

    //region Builder
    public BannerInfoMap defaultBanner() {
        this.withBannerID(0L);
        this.withTitle("Просто \"кончилась\" зима");
        this.withText(
                "\"Тестовое\" об'ъявление, &mdash &lquoteдлиной&rquote &quote75 символов '' &.");
        this.withHref("agent.mail.ru");
        this.withDomain("agent.mail.ru");
        this.withGeo("2,213,159");

        this.withPhrases(new BannerPhraseInfoMap(super.getPackageName()).defaultTextPhrase());
        this.withContacts(new ContactInfoMap(super.getPackageName()).defaultContacts());

        this.withSiteLinks(
                new SiteLinkMap(super.getPackageName()).siteLink1(),
                new SiteLinkMap(super.getPackageName()).siteLink2(),
                new SiteLinkMap(super.getPackageName()).siteLink3());

        this.withMinusKeywords(new String[]{"грузовые"});
        return this;
    }

    public BannerInfoMap defaultBannerWithNoLinks() {
        this.clear();
        this.withBannerID(0L);
        this.withTitle("Просто \"кончилась\" зима");
        this.withText(
                "\"Тестовое\" об'ъявление, &mdash &lquoteдлиной&rquote &quote75 символов '' &.");
        this.withGeo("2,213,159");

        this.withPhrases(new BannerPhraseInfoMap(super.getPackageName()).defaultTextPhrase());
        this.withContacts(new ContactInfoMap(super.getPackageName()).defaultContacts());

        this.withMinusKeywords(new String[]{"грузовые"});
        return this;
    }

    public BannerInfoMap defaultBannerWithNoContactsAndLinks() {
        this.clear();
        this.withBannerID(0L);
        this.withTitle("Просто \"кончилась\" зима");
        this.withText(
                "\"Тестовое\" об'ъявление, &mdash &lquoteдлиной&rquote &quote75 символов '' &.");
        this.withGeo("2,213,159");

        this.withPhrases(new BannerPhraseInfoMap(super.getPackageName()).defaultTextPhrase());
        this.withHref("agent.mail.ru");

        this.withMinusKeywords(new String[]{"грузовые"});
        return this;
    }

    public BannerInfoMap defaultBannerNoGroupFields() {
        this.clear();
        this.withBannerID(0L);
        this.withTitle(RandomStringUtils.randomAlphabetic(15));
        this.withText(RandomStringUtils.randomAlphabetic(15));
        this.withHref("agent.mail.ru");
        this.withSiteLinks(new SiteLinkMap(super.getPackageName()).siteLink1(),
                new SiteLinkMap(super.getPackageName()).siteLink2(),
                new SiteLinkMap(super.getPackageName()).siteLink3());
        return this;
    }

    public BannerInfoMap defaultEnglishBanner() {
        this.clear();
        this.withBannerID(0L);
        this.withTitle("English banner");
        this.withText(
                "Banner with english symbols");
        this.withHref("agent.mail.ru");
        this.withDomain("agent.mail.ru");
        this.withGeo("2,213,159");

        this.withPhrases(
                new BannerPhraseInfoMap(super.getPackageName()).defaultEnglishTextPhrase());
        this.withContacts(new ContactInfoMap(super.getPackageName()).defaultContacts());

        this.withSiteLinks(
                new SiteLinkMap(super.getPackageName()).siteLink("word1", "www.mail.ru/?edit=1/"),
                new SiteLinkMap(super.getPackageName()).siteLink("word2", "www.mail.ru/themes/?defskin=piter/"),
                new SiteLinkMap(super.getPackageName()).siteLink("word3", "wdgt.mail.ru/"));

        this.withMinusKeywords(new String[]{"minus"});
        return this;
    }

    public BannerInfoMap defaultEnglishBannerNoGroupFields() {
        this.clear();
        this.withBannerID(0L);
        this.withTitle(RandomStringUtils.random(7, RandomUtils.LATIN_CHARS));
        this.withText(RandomStringUtils.random(10, RandomUtils.UKRAIN_CHARS));
        this.withHref("agent.mail.ru");
        this.withSiteLinks(
                new SiteLinkMap(super.getPackageName()).siteLink("word1.1", "www.mail.ru/?edit=1/"),
                new SiteLinkMap(super.getPackageName()).siteLink("word2.2", "www.mail.ru/themes/?defskin=piter/"),
                new SiteLinkMap(super.getPackageName()).siteLink("word3.2", "wdgt.mail.ru/"));
        return this;
    }

    public BannerInfoMap withPhrases(BannerPhraseInfoMap... phrases) {
        this.put(PHRASES, null);
        if (phrases != null) {
            this.put(PHRASES,
                    convert(phrases, new BeanMapToBeanConverter())
                            .toArray((Object[]) Array.newInstance(
                                    new BannerPhraseInfoMap(super.getPackageName()).getBean().getClass(), 0)));
        }
        return this;
    }

    public BannerInfoMap withDefaultPhrases(int phraseCount) {
        this.put((PHRASES), null);
        Object[] phrasesData = new Object[phraseCount];
        PhraseTexts phraseTexts = new PhraseTexts();
        for (int i = 0; i < phraseCount; i++) {
            phrasesData[i] = new BannerPhraseInfoMap(super.getPackageName())
                    .defaultTextPhrase()
                    .withTextPhrase(phraseTexts.getNext())
                    .getBean();
        }
        this.put((PHRASES), JsonUtils.convertTo(
                phrasesData, Array.newInstance(
                        new BannerPhraseInfoMap(super.getPackageName()).getBean().getClass(), 1).getClass()));
        return this;
    }

    public BannerInfoMap withContacts(ContactInfoMap contacts) {
        this.put((CONTACT_INFO), (contacts == null) ? null : contacts.getBean());
        return this;
    }

    public BannerInfoMap withSiteLinks(SiteLinkMap... siteLinks) {
        Object[] siteLinkData = new Object[siteLinks.length];
        int i = 0;
        for (SiteLinkMap siteLink : siteLinks) {
            siteLinkData[i] = siteLink.getBean();
            i++;
        }
        this.put((SITELINKS), JsonUtils.convertTo(
                siteLinkData, Array.newInstance(
                        new SiteLinkMap(super.getPackageName()).getBean().getClass(), 1).getClass()));
        return this;
    }

    public BannerInfoMap withSiteLinks(List<SiteLinkMap> siteLinks) {
        Object[] siteLinkData = new Object[siteLinks.size()];
        int i = 0;
        for (SiteLinkMap siteLink : siteLinks) {
            siteLinkData[i] = siteLink.getBean();
            i++;
        }
        this.put((SITELINKS), JsonUtils.convertTo(
                siteLinkData, Array.newInstance(
                        new SiteLinkMap(super.getPackageName()).getBean().getClass(), 1).getClass()));
        return this;
    }

    public BannerInfoMap withMinusKeywords(String... minusKeywords) {
        this.put((MINUS_KEYWORDS), minusKeywords);
        return this;
    }

    public BannerInfoMap withAutoMinusWords(String autoMinusWords) {
        this.put((AUTO_MINUS_WORDS), autoMinusWords);
        return this;
    }

    public static List<String> firstLevelFields() {
        List<String> fieldNames = new ArrayList<String>();
        Field[] fields = ru.yandex.autotests.directapi.common.api4.BannerInfo.class.getDeclaredFields();
        for (Field field : fields) {
            if (!field.getName().startsWith("_") && !field.getName().equals("typeDesc")) {
                fieldNames.add(field.getName());
            }
        }
        return fieldNames;
    }

    public BannerInfoMap withCampaignID(int campaignID) {
        this.put((CAMPAIGN_ID), campaignID);
        return this;
    }

    public BannerInfoMap withCampaignID(Long campaignID) {
        return withCampaignID(campaignID.intValue());
    }

    public BannerInfoMap withBannerID(Long bannerID) {
        this.put((BANNER_ID), bannerID);
        return this;
    }

    public BannerInfoMap withAdGroupID(Long adGroupID) {
        this.put((AD_GROUP_ID), adGroupID);
        return this;
    }

    public BannerInfoMap withAdGroupName(String adGroupName) {
        this.put((AD_GROUP_NAME), adGroupName);
        return this;
    }

    public BannerInfoMap withGeo(String geo) {
        this.put((GEO), geo);
        return this;
    }

    public BannerInfoMap withGeo(long geo) {
        this.put((GEO), String.valueOf(geo));
        return this;
    }

    public BannerInfoMap withGeo(int geo) {
        this.put((GEO), String.valueOf(geo));
        return this;
    }

    public BannerInfoMap withTitle(String title) {
        this.put((TITLE), title);
        return this;
    }

    public BannerInfoMap withType(String type) {
        this.put((TYPE), type);
        return this;
    }

    public BannerInfoMap withAdGroupMobileBidAdjustment(Integer percentAdjustment) {
        this.put((AD_GROUP_MOBILE_BID_ADJUSTMENT), percentAdjustment);
        return this;
    }

    public BannerInfoMap withText(String text) {
        this.put((TEXT), text);
        return this;
    }

    public BannerInfoMap withHref(String href) {
        this.put((HREF), href);
        return this;
    }

    public BannerInfoMap withDomain(String domain) {
        this.put((DOMAIN), domain);
        return this;
    }

    public BannerInfoMap withAgeLabel(AgeLabel ageLabel) {
        this.put((AGE_LABEL), ageLabel.getAgeLabel());
        return this;
    }

    public BannerInfoMap withAgeLabel(String ageLabel) {
        this.put((AGE_LABEL), ageLabel);
        return this;
    }

    public BannerInfoMap withStatusSiteLinksModerate(String status) {
        put(STATUS_SITELINKS_MODERATE, status);
        return this;
    }

    public BannerInfoMap withAdImageHash(String adImageHash) {
        put(AD_IMAGE_HASH, adImageHash);
        return this;
    }

    public BannerInfoMap withStatusAdImageModerate(String statusAdImageModerate) {
        put(STATUS_AD_IMAGE_MODERATE, statusAdImageModerate);
        return this;
    }

    public BannerInfoMap withIsActive(String isActive) {
        put(IS_ACTIVE, isActive);
        return this;
    }

    public BannerInfoMap withStatusArchive(String status) {
        put(STATUS_ARCHIVE, status);
        return this;
    }

    public BannerInfoMap withStatusBannerModerate(String status) {
        put(STATUS_BANNER_MODERATE, status);
        return this;
    }

    public BannerInfoMap withStatusPhrasesModerate(String status) {
        put(STATUS_PHRASES_MODERATE, status);
        return this;
    }

    public BannerInfoMap withStatusPhoneModerate(String status) {
        put(STATUS_PHONE_MODERATE, status);
        return this;
    }

    public BannerInfoMap withStatusShow(String status) {
        put(STATUS_SHOW, status);
        return this;
    }
}

