package cz.moneta.test.harness.endpoints;

import cz.moneta.test.harness.connectors.mobile.AppiumMobileConnector;
import cz.moneta.test.harness.connectors.mobile.UnsupportedPlatformException;
import cz.moneta.test.harness.connectors.mobile.android.AndroidConnector;
import cz.moneta.test.harness.connectors.mobile.ios.IosConnector;
import cz.moneta.test.harness.endpoints.smartbanka.MobilePlatform;
import cz.moneta.test.harness.exception.HarnessException;
import cz.moneta.test.harness.support.mobile.MobileLookup;
import cz.moneta.test.harness.support.mobile.share.Direction;
import cz.moneta.test.harness.support.web.Clickable;
import cz.moneta.test.harness.support.web.TextContainer;
import cz.moneta.test.harness.support.web.Until;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;

public class MobileEndpoint<T extends AppiumMobileConnector> implements Endpoint {
    protected final ThreadLocal<T> connector;

    public MobileEndpoint(Supplier<T> connectorSupplier) {
        this.connector = ThreadLocal.withInitial(connectorSupplier);
    }

    public AndroidConnector getAndroid() {
        try {
            return (AndroidConnector) connector.get();
        } catch (ClassCastException e) {
            throw new UnsupportedPlatformException(MobilePlatform.ANDROID);
        }
    }

    public IosConnector getIos() {
        try {
            return (IosConnector) connector.get();
        } catch (ClassCastException e) {
            throw new UnsupportedPlatformException(MobilePlatform.IOS);
        }
    }

    public void click(Clickable clickable, MobileLookup mobileLookup) {
        connector.get().click(clickable.getPath(), mobileLookup);
    }

    public void acceptAlert(int timeout) {
        connector.get().acceptAlert(timeout);
    }

    public void dismissAlert(int timeout) {
        connector.get().dismissAlert(timeout);
    }

    public String getText(String path, MobileLookup mobileLookup) {
        return connector.get().getText(path, mobileLookup);
    }

    public String getText(String path) {
        return getText(path, MobileLookup.DEFAULT);
    }

    public void waitForElementsToLoad(int timeoutSeconds, MobileLookup mobileLookup, Until until, String... elementsToCheck) {
        connector.get().waitForElements(timeoutSeconds, mobileLookup, until, elementsToCheck);
    }

    public void sleepSeconds(int seconds) {
        try {
            TimeUnit.SECONDS.sleep(seconds);
        } catch (InterruptedException e) {
            //
        }
    }

    public void scroll(Direction direction) {
        switch (direction) {
            case UP:
                connector.get().scrollUp();
                break;
            case DOWN:
                connector.get().scrollDown();
                break;
            case RIGHT:
                connector.get().scrollRight();
                break;
            case LEFT:
                connector.get().scrollLeft();
                break;
            default:
                throw new HarnessException("unknown direction");
        }
    }

    public void scrollToElement(Direction direction, MobileLookup mobileLookup, String path) {
        switch (direction) {
            case UP:
                connector.get().scrollUpUntil(path, mobileLookup);
                break;
            case DOWN:
                connector.get().scrollDownUntil(path, mobileLookup);
                break;
            case LEFT:
                connector.get().scrollLeftUntil(path, mobileLookup);
                break;
            case RIGHT:
                connector.get().scrollRightUntil(path, mobileLookup);
                break;
            default:
                throw new HarnessException("unknown direction");
        }
    }

    public void swipeViewLeft(){
        connector.get().swipeViewLeft();
    }

    public void swipeViewRight(){
        connector.get().swipeViewRight();
    }

    public void swipeFromToElement(String source, String target, MobileLookup mobileLookup) {
        connector.get().swipeFromToElement(source, target, mobileLookup);
    }

    public void type(TextContainer input, String text, boolean clear, MobileLookup mobileLookup) {
        connector.get().type(input, text, clear, mobileLookup);
    }

    public void type(TextContainer input, String text, MobileLookup mobileLookup) {
        type(input, text, true, mobileLookup);

    }

    public void type(TextContainer input, String text) {
        type(input, text, true, MobileLookup.DEFAULT);

    }

    public void takeSnapshot(String prefix) {
        connector.get().takeSnapshot(getFileName(prefix, ".png"));
    }

    public void saveSources(String viewName) {
        connector.get().saveSource(getFileName(viewName, ".xml"));
    }

    public void captureVideo(String prefix) {
        connector.get().captureVideo(getFileName(prefix, ".mp4"));
    }

    public void resetApp() {
        connector.get().resetApp();
    }

    public void checkElementContent(String id, String content, MobileLookup mobileLookup) {
        connector.get().elementsCheck().checkElementContent(id, content, mobileLookup);
    }

    public void checkElementContent(String id, String content) {
        connector.get().elementsCheck().checkElementContent(id, content, MobileLookup.DEFAULT);
    }

    public void checkElementPresent(String path, MobileLookup mobileLookup){
        connector.get().elementsCheck().checkElementPresent(path, mobileLookup);
    }

    @Override
    public void close() {
        connector.get().close();
    }

    private String getFileName(String prefix, String suffix) {
        SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy/(HH.mm.ss)");
        Date date = new Date(System.currentTimeMillis());
        StringBuilder sb = new StringBuilder();
        if (prefix != null) {
            sb.append(prefix);
            sb.append("-");
        }
        sb.append(formatter.format(date));
        sb.append("-");
        sb.append(MobilePlatform.getMobilePlatformFromConfig(connector.get().getStore()));
        sb.append("-");
        sb.append(connector.get().getDeviceName());
        if (suffix != null) {
            sb.append(suffix);
        }
        return sb.toString();
    }
}
