package com.atlassian.bitbucket.test;

import com.jayway.restassured.RestAssured;
import com.jayway.restassured.http.ContentType;
import com.jayway.restassured.path.json.JsonPath;
import net.sf.json.JSONObject;

import java.util.concurrent.Callable;

import static javax.ws.rs.core.Response.Status.OK;
import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertEquals;

public class LicenseTestHelper {

    // The default number of licensed users in the system is 2. 'admin' and 'user'
    public static final int DEFAULT_LICENSED_USER_COUNT = 2;

    public static final BitbucketTestLicense SINGLE_USER_LICENSE = BitbucketTestLicense.builder()
            .whenClustered(
                    "AAABMg0ODAoPeNp9UdFqwjAUffcrAnuuNKkwJgSmbRTBVln1YY934VYDNZWbVObfL9YIGwwhD+Gck\n" +
                            "3PPPXlZkGEFasYF49mUi2n2xpbljomUT0bOgzuO1QXaHrzprGygdRjhAp0mcx7w2thDi6x3SKw1G\n" +
                            "q1D1nTEPDofqPgiJxxsCvAowwCRpFmSvj7YznrQvoITyiV2TcNyAmMjW4arRwtWo/o+G7pGE5EmK\n" +
                            "Q8nyoKBuaD01ONfWxUMWnnQN8t38C04Z8COdXeKulpVkotsMqqRLkirQs7Vfp2IImSs1HyV1J/LW\n" +
                            "dSu7yvurmcc4uabslQf+Wq2joItkLdIAxmhDR3AGnfvsb5BbNFbzXahIveoFDzkGPak3xtse9JHc\n" +
                            "Ph/bTHLs1Kq/vSFtGn24Xuc5KMf6LOp4DAsAhRUNDa4MG5ybx1ePBFUhWtIreodPgIUGLMhHJgU3\n" +
                            "XAY3PyxXEeZ1OAzVcU=X02fb")
            .whenNonClustered(
                    "AAABKg0ODAoPeNp9UNFqwjAUffcrAnuupNUhCIFpm0nBVlkrY4932W0N1FRuUpl/v1izB/cwyENyz\n" +
                            "rkn95ynd/xiBRDjCxbz5Xy+fF4wWdUs4XEysQ7scSov0A3gdG9EA53FAGdoFenziFfatB2ywSKxT\n" +
                            "is0FlnTE3NonafCREo42mTgUNw+iPgs4otftjcOlCvhhGKDfdOwlECbwBb+6tCAUSi/z5quwSThE\n" +
                            "Y/9CTJvoC8oHA34aCu9QSdadbN8AdeBtRrMVPWnoKtkKeJkNg/P7T1FfT3juFG6Kwr5luar7aRCu\n" +
                            "iDlmVjLwzZKMh+ilOs8qj42qzC9B3IGaZwM0I5aMNree6xuEHsdjGK1r8gGTTmcPpF2zcH3aEX8u\n" +
                            "Mp/sfcDqSNY/NvsDwp0ocgwLQIVAI0R9FKxOPeWevWwkPN8i1Mrjw95AhR6RSuj4xrxEy7SFE+kS\n" +
                            "PFYPFVmjw==X02f3")
            .build();

    public static JSONObject createLicenseBody(String license) {
        JSONObject body = new JSONObject();
        body.put("license", license);

        return body;
    }

    public static <T> T doWithLicense(Callable<T> runnable) throws Exception {
        String original = getLicense();

        try {
            return runnable.call();
        } finally {
            setLicense(original);
        }
    }

    public static String getLicense() {
        return getLicenseJson().getString("license");
    }

    public static JsonPath getLicenseJson() {
        return RestAssured.expect()
                .statusCode(OK.getStatusCode())
                .given()
                .auth().preemptive().basic(DefaultFuncTestData.getAdminUser(), DefaultFuncTestData.getAdminPassword())
                .when()
                .get(getLicenseURL())
                .getBody().jsonPath();
    }

    public static void ensureLicensedUserCount(int expected) {
        // 10 seconds should be plenty of time for the license count to repopulate correctly
        long timeout = System.currentTimeMillis() + 10000L;
        int actual;
        do {
            actual = getLicensedUserCount();
            if (actual == expected) {
                return;
            }
        } while (timeout > System.currentTimeMillis());
        assertEquals("License count should match (users=" + UserTestHelper.allUsernames() + ")", expected, actual);
    }

    public static int getLicensedUserCount() {
        return LicenseTestHelper.getLicenseJson().getInt("status.currentNumberOfUsers");
    }

    public static void setLicense(String license) {
        RestAssured.expect()
                .statusCode(OK.getStatusCode())
                .body("license", equalTo(license))
                .log().ifError()
                .given()
                .auth().preemptive().basic(DefaultFuncTestData.getAdminUser(), DefaultFuncTestData.getAdminPassword())
                .when()
                .body(createLicenseBody(license))
                .contentType(ContentType.JSON)
                .post(getLicenseURL());
    }


    public static String getLicenseURL() {
        return DefaultFuncTestData.getRestURL() + "/admin/license";
    }
}
