/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package system;

import com.cloudant.client.api.CloudantClient;
import com.cloudant.client.api.Database;
import com.google.gson.*;
import com.jayway.restassured.response.Response;
import common.Pair;
import common.TestUtils;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.Date;
import java.util.Map;
import java.util.Properties;
import java.util.UUID;

import static com.jayway.restassured.RestAssured.given;
import static org.junit.Assert.assertTrue;

/**
 * Basic tests of the cloudant trigger function.
 */
public class CloudantUtil {
    public static final String USER_PROPERTY = "user";
    public static final String PWD_PROPERTY = "password";
    public static final String DBNAME_PROPERTY = "dbname";
    public static final String DOC_ID = "testId";

    /**
     * The root of the Cloudant installation.
     */
    private static final String CLOUDANT_INSTALL_FILE = "installCatalog.sh";
    private static final String CLOUDANT_HOME = getCloudantHome();
    public static final File ATTACHMENT_FILE_PATH = getFileRelativeToCloudantHome("tests/dat/attach.txt");
    public static final File INDEX_DDOC_PATH = getFileRelativeToCloudantHome("tests/dat/indexdesigndoc.txt");
    public static final File VIEW_AND_SEARCH_DDOC_PATH = getFileRelativeToCloudantHome("tests/dat/searchdesigndoc.txt");
    public static final File FILTER_DDOC_PATH = getFileRelativeToCloudantHome("tests/dat/filterdesigndoc.txt");


    private static Gson gson = new Gson();

    public static class Credential {
        public final String user;
        public final String password;
        public final String dbname;

        public String host() {
            return user + ".cloudant.com";
        }

        public Credential(String user, String password, String dbname) {
            this.user = user;
            this.password = password;
            this.dbname = dbname;
        }

        public Credential(Properties props) {
            this(props.getProperty(USER_PROPERTY), props.getProperty(PWD_PROPERTY), props.getProperty(DBNAME_PROPERTY));
        }

        public static Credential makeFromVCAPFile(String vcapService, String dbNamePrefix) {
            // Create database name using dbNamePrefix and generated uuid
            String uniqueSuffix = UUID.randomUUID().toString().replace("-", "");
            String dbname = dbNamePrefix.toLowerCase() + "-" + uniqueSuffix;

            Map<String,String> credentials = TestUtils.getVCAPcredentials(vcapService);
            String username = credentials.get("username");
            String password = credentials.get("password");
            Properties props = new Properties();
            props.setProperty(USER_PROPERTY, username);
            props.setProperty(PWD_PROPERTY, password);
            props.setProperty(DBNAME_PROPERTY, dbname);
            return new Credential(props);
        }

    }

    public static void setUp(Credential credential) throws Exception {
        deleteTestDatabase(credential);
        for (int i = 0; i < 5; i++) {
            try {
                Pair<Integer, JsonObject> response = CloudantUtil.createTestDatabase(credential, false);
                if (response.fst == 201)
                    return;
                // respond code is sometimes not 201 but still ok
                // (might be 200 or 202)
                if (response.snd.has("ok")) {
                    if (response.snd.get("ok").getAsBoolean())
                        return;
                }
                if (response.snd.has("reason")) {
                    String reason = response.snd.get("reason").getAsString();
                    if (reason.contains("exists"))
                        return;
                }
            } catch (Throwable t) {
                Thread.sleep(1000);
            }
        }
        assertTrue("failed to create database " + credential.dbname, false);
    }

    public static void unsetUp(Credential credential) throws Exception {
        deleteTestDatabase(credential);
    }

    /**
     * Delete a user-specific Cloudant database.
     *
     * @throws UnsupportedEncodingException
     * @throws InterruptedException
     */
    public static JsonObject deleteTestDatabase(Credential credential) throws UnsupportedEncodingException, InterruptedException {
        return deleteTestDatabase(credential, null);
    }

    public static JsonObject deleteTestDatabase(Credential credential, String dbName) throws UnsupportedEncodingException, InterruptedException {
        // Use DELETE to delete the database.
        // This could fail if the database already exists, but that's ok.
        Response response = null;
        String db = (dbName != null && !dbName.isEmpty()) ? dbName : credential.dbname;
        assertTrue("failed to determine database name", db != null && !db.isEmpty());
        response = given().port(443).baseUri(cloudantAccount(credential.user)).auth().basic(credential.user, credential.password).when().delete("/" + db);
        System.out.format("Response of delete database %s: %s\n", db, response.asString());
        return (JsonObject) new JsonParser().parse(response.asString());
    }

    /**
     * Create a user-specific Cloudant database that will be used for this test.
     *
     * @throws UnsupportedEncodingException
     */
    public static Pair<Integer, JsonObject> createTestDatabase(Credential credential) throws UnsupportedEncodingException {
        return createTestDatabase(credential, true);
    }

    private static Pair<Integer, JsonObject> createTestDatabase(Credential credential, boolean failIfCannotCreate) throws UnsupportedEncodingException {
        // Use PUT to create the database.
        // This could fail if the database already exists, but that's ok.
        String dbName = credential.dbname;
        assertTrue("failed to determine database name", dbName != null && !dbName.isEmpty());
        Response response = given().port(443).baseUri(cloudantAccount(credential.user)).auth().basic(credential.user, credential.password).when().put("/" + dbName);
        System.out.format("Response of create database %s: %s\n", dbName, response.asString());
        if (failIfCannotCreate)
            assertTrue("failed to create database " + dbName, response.statusCode() == 201 || response.statusCode() == 202);
        return Pair.make(response.statusCode(), (JsonObject) new JsonParser().parse(response.asString()));
    }

    /**
     * read a user-specific Cloudant database to verify database action test
     * cases.
     *
     * @throws UnsupportedEncodingException
     */
    public static JsonObject readTestDatabase(Credential credential) {
        try {
            String db = credential.dbname;
            Response response = given().port(443).baseUri(cloudantAccount(credential.user)).auth().basic(credential.user, credential.password).when().get("/" + db);
            System.out.format("Response of HTTP GET for database %s: %s\n", credential.dbname, response.asString());
            return gson.fromJson(response.asString(), JsonObject.class);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    public static Response readTestDatabase(Credential credential, String dbName) {
        try {
            String db = (dbName != null && !dbName.isEmpty()) ? dbName : credential.dbname;
            Response response = given().port(443).baseUri(cloudantAccount(credential.user)).auth().basic(credential.user, credential.password).when().get("/" + db);
            System.out.format("Response of HTTP GET for database %s: %s\n", credential.dbname, response.asString());
            return response;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * create a document in the cloudant database
     *
     * @throws UnsupportedEncodingException
     */
    public static JsonObject createDocument(Credential credential, String jsonObj) throws UnsupportedEncodingException {
        JsonObject obj = new JsonParser().parse(jsonObj).getAsJsonObject();

        CloudantClient client = new CloudantClient(credential.user, credential.user, credential.password);
        Database db = client.database(credential.dbname, false);
        com.cloudant.client.api.model.Response res = db.post(obj);
        client.shutdown();

        JsonObject ret = new JsonObject();
        ret.addProperty("ok", true);
        ret.addProperty("id", res.getId());
        ret.addProperty("rev", res.getRev());
        return ret;
    }

    /**
     * get a document from the cloudant database
     *
     * @throws UnsupportedEncodingException
     */
    public static JsonObject getDocument(Credential credential, String docId) throws UnsupportedEncodingException {
        // use GET to get the document
        Response response = given().port(443).baseUri(cloudantAccount(credential.user)).auth().basic(credential.user, credential.password).get("/" + credential.dbname + "/" + docId);
        String responseStr = response.asString();
        if (responseStr.length() > 500)
            responseStr = responseStr.substring(0, 500);
        System.out.format("Response of get document from database %s: %s\n", credential.dbname, responseStr);
        return (JsonObject) new JsonParser().parse(response.asString());
    }

    /**
     * delete a document from the cloudant database
     *
     * @throws UnsupportedEncodingException
     */
    public static JsonObject deleteDocument(Credential credential, JsonObject jsonObj) throws UnsupportedEncodingException {
        CloudantClient client = new CloudantClient(credential.user, credential.user, credential.password);
        Database db = client.database(credential.dbname, false);
        com.cloudant.client.api.model.Response res = null;
        try {
            res = db.remove(jsonObj);
        }
        catch(Exception e) {
            System.out.format("Exception thrown during document delete: %s", e.toString());
        }
        finally {
            client.shutdown();
        }

        JsonObject ret = new JsonObject();
        ret.addProperty("id", res.getId());
        ret.addProperty("rev", res.getRev());
        return ret;
    }

    /**
     * Read bulk documents from the cloudant database
     *
     * @throws UnsupportedEncodingException
     */
    public static JsonArray bulkDocuments(Credential credential, JsonArray bulkDocs) throws UnsupportedEncodingException {
        JsonObject docs = new JsonObject();
        docs.add("docs", bulkDocs);
        // use GET to get the document
        String dbname = credential.dbname;
        Response response = given().port(443).baseUri(cloudantAccount(credential.user)).auth().basic(credential.user, credential.password).contentType("application/json").body(docs.toString()).post("/" + credential.dbname + "/_bulk_docs?include_docs=true");
        String responseStr = response.asString();
        if (responseStr.length() > 500)
            responseStr = responseStr.substring(0, 500);
        System.out.format("Response of get document from database %s: %s\n", dbname, responseStr);
        return (JsonArray) new JsonParser().parse(response.asString());
    }

    public static JsonObject createDocParameterForWhisk() {
        return createDocParameterForWhisk(null);
    }

    public static JsonObject createDocParameterForWhisk(String doc) {
        JsonObject cloudantDoc = new JsonObject();
        String now = new Date().toString();
        cloudantDoc.addProperty("_id", DOC_ID);
        cloudantDoc.addProperty("date", now);
        // Create JSON object that will be passed as an argument to whisk cli
        JsonObject param = new JsonObject();
        if (doc != null && !doc.isEmpty()) {
            param.addProperty("doc", doc);
        } else {
            param.addProperty("doc", cloudantDoc.toString());
        }
        return param;
    }

    public static JsonArray createDocumentArray(int numDocs) {
        // Array of docs for bulk
        JsonArray bulkDocs = new JsonArray();
        for (int i = 1; i <= numDocs; i++) {
            JsonObject cloudantDoc = new JsonObject();
            String now = new Date().toString();
            cloudantDoc.addProperty("_id", CloudantUtil.DOC_ID + i);
            cloudantDoc.addProperty("date", now);
            bulkDocs.add(cloudantDoc);
        }
        return bulkDocs;
    }

    /**
     * Only keep _id and _rev for each document in the JSON array.
     */
    public static JsonArray updateDocsWithOnlyIdAndRev(JsonArray docs) {
        for (int i = 0; i < docs.size(); i++) {
            JsonElement id = docs.get(i).getAsJsonObject().get("id");
            JsonElement rev = docs.get(i).getAsJsonObject().get("rev");
            docs.get(i).getAsJsonObject().add("_id", id);
            docs.get(i).getAsJsonObject().add("_rev", rev);
        }
        return docs;
    }

    public static JsonArray addDeletedPropertyToDocs(JsonArray docs) {
        for (int i = 0; i < docs.size(); i++) {
            JsonElement id = docs.get(i).getAsJsonObject().get("id");
            JsonElement rev = docs.get(i).getAsJsonObject().get("rev");
            docs.get(i).getAsJsonObject().add("_id", id);
            docs.get(i).getAsJsonObject().add("_rev", rev);
            docs.get(i).getAsJsonObject().addProperty("_deleted", true);
        }
        return docs;
    }

    public static JsonObject createDesignFromFile(File jsonFile) throws JsonSyntaxException, IOException {
        return gson.fromJson(readFile(jsonFile), JsonObject.class);
    }

    public static String readFile(File jsonFile) throws IOException {
        return new String(Files.readAllBytes(jsonFile.toPath()), StandardCharsets.UTF_8);
    }

    /**
     * Create an index in the cloudant database
     *
     * @throws UnsupportedEncodingException
     */
    public static JsonObject createIndex(Credential credential, String jsonObj) throws UnsupportedEncodingException {
        Response response = given().port(443).baseUri(cloudantAccount(credential.user)).auth().basic(credential.user, credential.password).contentType("application/json").body(jsonObj).when().post("/" + credential.dbname + "/_index");
        System.out.format("Response of create document in database %s: %s\n", credential.dbname, response.asString());
        assertTrue("failed to create index in database " + credential.dbname, response.statusCode() == 200);
        return (JsonObject) new JsonParser().parse(response.asString());
    }

    /**
     * Create a document with attachment in a cloudant database
     *
     * @throws UnsupportedEncodingException
     * @throws FileNotFoundException
     */
    public static com.cloudant.client.api.model.Response createDocumentWithAttachment(Credential credential, File attachmentFilePath) throws UnsupportedEncodingException, FileNotFoundException {
        InputStream attachStream = new FileInputStream(attachmentFilePath);
        String contentType = "text/plain";

        CloudantClient client = new CloudantClient(credential.user, credential.user, credential.password);
        Database db = client.database(credential.dbname, false);
        return db.saveAttachment(attachStream, attachmentFilePath.getName(), contentType);
    }

    private static String cloudantAccount(String user) {
        return "https://" + user + ".cloudant.com";
    }

    public static File getFileRelativeToCloudantHome(String name) {
        return new File(CLOUDANT_HOME, name);
    }

    private static String getCloudantHome() {
        String dir = System.getProperty("user.dir");

        if (dir != null) {
            // Look in the directory tree recursively.
            File propfile = findFileRecursively(dir, CLOUDANT_INSTALL_FILE);
            return propfile != null ? propfile.getParent() : null;
        } else return null;
    }

    private static File findFileRecursively(String dir, String needle) {
        if (dir != null) {
            File base = new File(dir);
            File file = new File(base, needle);
            if (file.exists()) {
                return file;
            } else {
                return findFileRecursively(base.getParent(), needle);
            }
        } else return null;
    }

}
