package com.atlassian.webdriver.bitbucket.page;

import com.atlassian.pageobjects.DelayedBinder;
import com.atlassian.pageobjects.elements.ElementBy;
import com.atlassian.pageobjects.elements.PageElement;
import com.atlassian.pageobjects.elements.query.Poller;
import com.atlassian.pageobjects.elements.query.Queries;
import com.atlassian.pageobjects.elements.query.TimedCondition;
import com.google.common.base.Supplier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.TimeUnit;

import static org.hamcrest.Matchers.is;
import static org.junit.Assert.fail;

public class MaintenancePage extends AbstractPage {

    private static final Logger log = LoggerFactory.getLogger(MaintenancePage.class);

    @ElementBy(className = "cancel-link")
    private PageElement unlockLink;

    @ElementBy(id = "cancel")
    private PageElement unlockButton;

    @ElementBy(id = "cancelToken")
    private PageElement unlockToken;

    @Override
    public String getUrl() {
        return "/unavailable";
    }

    public <P extends AbstractPage> P waitUntilCompleted(Class<P> nextPage, Object... args) {
        final DelayedBinder<P> delayedBinder = pageBinder.delayedBind(nextPage, args);
        try {
            Poller.waitUntil(Queries.forSupplier(timeouts, new Supplier<Boolean>() {
                long lastLog = System.currentTimeMillis();
                long logEvery = TimeUnit.SECONDS.toMillis(5);
                public Boolean get() {
                    // STASHDEV-4976: Add debugging for why migration is timing out when it actually seems to succeed
                    if (log.isWarnEnabled() && (System.currentTimeMillis() - logEvery > lastLog)) {
                        lastLog = System.currentTimeMillis();
                        log.warn(String.format("Waiting for %s; got %s", delayedBinder.get().getUrl(), driver.getCurrentUrl()));
                    }
                    return AbstractPage.isOnPage(driver, delayedBinder.get());
                }
            }), is(true), Poller.by(10,  TimeUnit.MINUTES));
        } catch (AssertionError e) {
            fail(String.format("Maintenance failed to complete and redirect.\n\t\tExpected: %s\n\t\tActual: %s", delayedBinder.get().getUrl(), driver.getCurrentUrl()));
        }
        return delayedBinder.bind();
    }

    public TimedCondition hasUnlockLink() {
        return unlockLink.timed().isPresent();
    }

    public MaintenancePage clickUnlockLink() {
        unlockLink.click();
        return this;
    }

    public MaintenancePage setUnlockToken(String token) {
        unlockToken.type(token);
        return this;
    }

    public MaintenancePage clickUnlockButton() {
        unlockButton.click();
        return this;
    }
}
