package org.whoneedhelp.mobile;

import static androidx.test.espresso.web.assertion.WebViewAssertions.webMatches;
import static androidx.test.espresso.web.sugar.Web.onWebView;
import static androidx.test.espresso.web.webdriver.DriverAtoms.findElement;
import static androidx.test.espresso.web.webdriver.DriverAtoms.getText;
import static org.hamcrest.Matchers.containsString;

import android.content.Context;
import android.content.Intent;
import android.net.Uri;

import androidx.test.core.app.ActivityScenario;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.espresso.web.webdriver.Locator;
import androidx.test.ext.junit.runners.AndroidJUnit4;

import org.junit.Test;
import org.junit.runner.RunWith;

import java.util.concurrent.TimeUnit;

@RunWith(AndroidJUnit4.class)
public final class PublicStagingInstrumentedTest {
    private static final long PAGE_TIMEOUT_SECONDS = 45;

    private final Context context = ApplicationProvider.getApplicationContext();

    @Test
    public void publicHomeAndSafetyDeepLinkRenderExpectedDom() throws Exception {
        try (ActivityScenario<MainActivity> scenario = launch("/")) {
            waitForElementText(
                "main-content",
                "Help can be closer than you think."
            );
        }

        try (ActivityScenario<MainActivity> scenario = launch("/safety")) {
            waitForElementText("main-content", "Safety rules");
        }
    }

    private ActivityScenario<MainActivity> launch(String path) {
        Intent intent = new Intent(
            Intent.ACTION_VIEW,
            Uri.parse(BuildConfig.BASE_URL + path),
            context,
            MainActivity.class
        );
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        return ActivityScenario.launch(intent);
    }

    private static void waitForElementText(String id, String expected)
        throws InterruptedException {
        long deadline =
            System.nanoTime() + TimeUnit.SECONDS.toNanos(PAGE_TIMEOUT_SECONDS);
        Throwable lastFailure = null;

        while (System.nanoTime() < deadline) {
            try {
                onWebView()
                    .withElement(findElement(Locator.ID, id))
                    .check(webMatches(getText(), containsString(expected)));
                return;
            } catch (AssertionError | RuntimeException failure) {
                lastFailure = failure;
                Thread.sleep(250);
            }
        }

        AssertionError timeout = new AssertionError(
            "WebView element #" + id + " did not contain: " + expected
        );

        if (lastFailure != null) {
            timeout.initCause(lastFailure);
        }

        throw timeout;
    }
}
