package ru.yandex.autotests.directapi.images.adimage.upload;

import java.util.Arrays;
import java.util.List;

import org.apache.commons.lang.RandomStringUtils;
import org.junit.BeforeClass;
import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.Test;

import ru.yandex.aqua.annotations.project.Aqua;
import ru.yandex.autotests.direct.db.models.jooq.ppc.enums.BannerImagesFormatsImageType;
import ru.yandex.autotests.directapi.apiclient.config.Semaphore;
import ru.yandex.autotests.directapi.apiclient.errors.AxisError;
import ru.yandex.autotests.directapi.apiclient.errors.AxisErrorDetails;
import ru.yandex.autotests.directapi.apiclient.methods.Method;
import ru.yandex.autotests.directapi.common.api45.AdImage;
import ru.yandex.autotests.directapi.common.api45.AdImageResponse;
import ru.yandex.autotests.directapi.common.api45.AdImageUpload;
import ru.yandex.autotests.directapi.enums.ImageType;
import ru.yandex.autotests.directapi.images.ImageLogins;
import ru.yandex.autotests.directapi.images.ImagesFeatures;
import ru.yandex.autotests.directapi.model.images.AdImageRequestMap;
import ru.yandex.autotests.directapi.model.images.AdImageSelectionCriteriaMap;
import ru.yandex.autotests.directapi.model.images.AdImageURLMap;
import ru.yandex.autotests.directapi.rules.ApiSteps;
import ru.yandex.autotests.directapi.rules.Trashman;
import ru.yandex.autotests.directapi.steps.banners.ImagesSteps;
import ru.yandex.autotests.irt.testutils.allure.LogSteps;
import ru.yandex.qatools.allure.annotations.Features;
import ru.yandex.qatools.hazelcast.SemaphoreRule;

import static ch.lambdaj.Lambda.collect;
import static ch.lambdaj.Lambda.on;
import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.notNullValue;
import static org.junit.Assert.assertThat;

/**
 * User: mariabye
 * Date: 23.05.13
 */
@Aqua.Test
@Features(ImagesFeatures.AD_IMAGE_UPLOAD)
public class ImageUrlTest {
    private LogSteps log = LogSteps.getLogger(this.getClass());

    private static String login = ImageLogins.LOGIN_UPLOAD_2;

    @ClassRule
    public static ApiSteps api = new ApiSteps().version(104).as(login);

    @ClassRule
    public static SemaphoreRule semaphore = Semaphore.getSemaphore();

    @Rule
    public Trashman trashman = new Trashman(api);

    private static String name = RandomStringUtils.randomAlphabetic(5);

    @BeforeClass
    public static void deleteImages() {
        api.userSteps.imagesSteps().adImageDeleteForLogin(login);
    }

    @Test
    @ru.yandex.qatools.allure.annotations.TestCaseId("7501")
    public void uploadImageWithValidUrl() {
        String url = ImagesSteps.getDefaultImageUrl(5, ImageType.REGULAR);
        AdImageResponse uploadResponse = api.userSteps.imagesSteps().adImageUpload(
                new AdImageURLMap(api.type())
                        .withName(name)
                        .withURL(url)
        );
        AdImageUpload[] uploads = api.userSteps.imagesSteps().getAdImageUploads(
                new AdImageSelectionCriteriaMap(api.type()).withAdImageUploadTaskIDS(
                        ImagesSteps.extractAdImageUploadTaskIDS(uploadResponse.getActionsResult())
                ));
        List<String> urls = collect(uploads, on(AdImageUpload.class).getSourceURL());
        assertThat("Неверный адрес картинки", urls, contains(url));
    }

    @Test
    @ru.yandex.qatools.allure.annotations.TestCaseId("8882")
    public void uploadImageWithSomeValidUrlsDifferentTypes() {
        AdImageResponse uploadResponse = api.userSteps.imagesSteps().adImageUpload(
                new AdImageURLMap(api.type())
                        .withName("regular")
                        .withURL(ImagesSteps.getDefaultImageUrl(1, ImageType.REGULAR)),
                new AdImageURLMap(api.type())
                        .withName("wide")
                        .withURL(ImagesSteps.getDefaultImageUrl(1, ImageType.WIDE))
        );
        AdImageUpload[] uploads = api.userSteps.imagesSteps().getAdImageUploads(
                new AdImageSelectionCriteriaMap(api.type()).withAdImageUploadTaskIDS(
                        ImagesSteps.extractAdImageUploadTaskIDS(uploadResponse.getActionsResult())
                ));
        assertThat("верное кол-во полученных объектов", uploads.length, equalTo(2));
    }


    @Test
    public void successUploadRegularImageIfHaveOldSmall() {
        AdImage adImage = api.userSteps.imagesSteps().uploadRawImage("adidas",
                "https://direct-qa.s3.mds.yandex.net/images/adidas600x450.jpg", login);
        String smallAdImageHash = adImage.getAdImageHash();
        int shard = api.userSteps.clientFakeSteps().getUserShard(login);
        api.userSteps.getDirectJooqDbSteps().useShardForLogin(login)
                .imagesSteps().setImageType(smallAdImageHash, BannerImagesFormatsImageType.small);

        AdImageResponse uploadResponse = api.userSteps.imagesSteps().adImageUpload(
                new AdImageURLMap(api.type())
                        .withName("regular")
                        .withURL(ImagesSteps.getDefaultImageUrl(7, ImageType.REGULAR))
        );
        AdImageUpload[] uploads = api.userSteps.imagesSteps().getAdImageUploads(
                new AdImageSelectionCriteriaMap(api.type()).withAdImageUploadTaskIDS(
                        ImagesSteps.extractAdImageUploadTaskIDS(uploadResponse.getActionsResult())
                ));
        assertThat("верное кол-во полученных объектов", uploads.length, equalTo(1));

        api.userSteps.getDirectJooqDbSteps().useShardForLogin(login)
                .imagesSteps().deleteBannerImagesFormatsRecord(smallAdImageHash);
    }

    @Test
    public void successUploadWideImageIfHaveOldSmall() {
        AdImage adImage = api.userSteps.imagesSteps().uploadRawImage("birds",
                "https://direct-qa.s3.mds.yandex.net/images/birds600x450.jpg", login);
        String smallAdImageHash = adImage.getAdImageHash();
        int shard = api.userSteps.clientFakeSteps().getUserShard(login);

        api.userSteps.getDirectJooqDbSteps().useShardForLogin(login)
                .imagesSteps().setImageType(smallAdImageHash, BannerImagesFormatsImageType.small);
        AdImageResponse uploadResponse = api.userSteps.imagesSteps().adImageUpload(

                new AdImageURLMap(api.type())
                        .withName("wide")
                        .withURL(ImagesSteps.getDefaultImageUrl(1, ImageType.WIDE))
        );
        AdImageUpload[] uploads = api.userSteps.imagesSteps().getAdImageUploads(
                new AdImageSelectionCriteriaMap(api.type()).withAdImageUploadTaskIDS(
                        ImagesSteps.extractAdImageUploadTaskIDS(uploadResponse.getActionsResult())
                ));
        assertThat("верное кол-во полученных объектов", uploads.length, equalTo(1));

        api.userSteps.getDirectJooqDbSteps().useShardForLogin(login)
                .imagesSteps().deleteBannerImagesFormatsRecord(smallAdImageHash);
    }

    @Test
    @ru.yandex.qatools.allure.annotations.TestCaseId("7502")
    public void uploadImageWithIPUrl() {
        String url = "https://direct-qa.s3.mds.yandex.net/images/old/img1.jpg";
        AdImageResponse uploadResponse = api.userSteps.imagesSteps().adImageUpload(
                new AdImageURLMap(api.type())
                        .withName(name)
                        .withURL(url)
        );
        AdImageUpload[] uploads = api.userSteps.imagesSteps().getAdImageUploads(
                new AdImageSelectionCriteriaMap(api.type()).withAdImageUploadTaskIDS(
                        ImagesSteps.extractAdImageUploadTaskIDS(uploadResponse.getActionsResult())
                ));
        List<String> urls = collect(uploads, on(AdImageUpload.class).getSourceURL());
        assertThat("Неверный адрес картинки", urls, contains(url));
    }


    @Test
    @ru.yandex.qatools.allure.annotations.TestCaseId("7503")
    public void uploadImageWithUndefUrl() {
        AdImageResponse response = api.userSteps.imagesSteps().adImageUpload(
                new AdImageURLMap(api.type())
                        .withLogin(login)
                        .withName(name)
                        .withURL(null)
        );
        api.userSteps.imagesSteps().responseShouldContainErrors(
                response,
                new AxisError(71, AxisErrorDetails.FIELD_MUST_NOT_BE_EMPTY, "AdImageURLData[0].URL")
        );
    }

    @Test
    @ru.yandex.qatools.allure.annotations.TestCaseId("7504")
    public void uploadImageWithEmptyUrl() {
        AdImageResponse response = api.userSteps.imagesSteps().adImageUpload(
                new AdImageURLMap(api.type())
                        .withLogin(login)
                        .withName(name)
                        .withURL("")
        );
        api.userSteps.imagesSteps().responseShouldContainErrors(
                response,
                new AxisError(71, AxisErrorDetails.FIELD_SHOULD_CONTAIN_A_URL, "AdImageURLData[0].URL")
        );
    }

    @Test
    @ru.yandex.qatools.allure.annotations.TestCaseId("7505")
    public void uploadImageWith404Url() {
        AdImageResponse uploadResponse = api.userSteps.imagesSteps().adImageUpload(
                new AdImageURLMap(api.type())
                        .withName(name)
                        .withURL("http://yandex.ru/123")
        );
        int[] taskIDs = ImagesSteps.extractAdImageUploadTaskIDS(uploadResponse.getActionsResult());
        assertThat("Неверный адрес картинки", Arrays.asList(taskIDs), contains(notNullValue()));
    }

    @Test
    @ru.yandex.qatools.allure.annotations.TestCaseId("7506")
    public void uploadImageWithWrongContentTypeUrl() {
        AdImageResponse uploadResponse = api.userSteps.imagesSteps().adImageUpload(
                new AdImageURLMap(api.type())
                        .withName(name)
                        .withURL("http://yandex.ru")
        );
        int[] taskIDs = ImagesSteps.extractAdImageUploadTaskIDS(uploadResponse.getActionsResult());
        assertThat("Неверный адрес картинки", Arrays.asList(taskIDs), contains(notNullValue()));
    }

    @Test
    @ru.yandex.qatools.allure.annotations.TestCaseId("7507")
    public void uploadImageWithCyrillicUrl() {
        AdImageResponse uploadResponse = api.userSteps.imagesSteps().adImageUpload(
                new AdImageURLMap(api.type())
                        .withName(name)
                        .withURL("http://павелниколаевич.рф/")
        );
        int[] taskIDs = ImagesSteps.extractAdImageUploadTaskIDS(uploadResponse.getActionsResult());
        assertThat("Неверный адрес картинки", Arrays.asList(taskIDs), contains(notNullValue()));
    }

    @Test
    @ru.yandex.qatools.allure.annotations.TestCaseId("7508")
    public void uploadImageOverLimitNumberOfUrl() {
        AdImageURLMap[] urls = new AdImageURLMap[ImagesSteps.AD_IMAGE_HASHES_MAX_VALUE + 1];
        for (int i = 0; i < ImagesSteps.AD_IMAGE_HASHES_MAX_VALUE + 1; i++) {
            AdImageURLMap imageURL = new AdImageURLMap(api.type())
                    .withURL("http://" + RandomStringUtils.randomAlphabetic(20) + ".ru")
                    .withName(name);
            urls[i] = imageURL;
        }
        api.userSteps.imagesSteps().shouldGetErrorOn(
                Method.AD_IMAGE,
                new AdImageRequestMap<>(api.type()).upload(
                        urls
                ),
                new AxisError(241, AxisErrorDetails.THE_ARRAY_MUST_CONTAIN_NO_MORE_THAN_N_ELEMENTS
                        , "AdImageURLData", ImagesSteps.AD_IMAGE_HASHES_MAX_VALUE)
        );
    }
}
