/*
 * 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 org.apache.guacamole.vault.ksm.secret;

import com.google.inject.Singleton;
import com.keepersecurity.secretsManager.core.HiddenField;
import com.keepersecurity.secretsManager.core.Host;
import com.keepersecurity.secretsManager.core.Hosts;
import com.keepersecurity.secretsManager.core.KeeperFile;
import com.keepersecurity.secretsManager.core.KeeperRecord;
import com.keepersecurity.secretsManager.core.KeeperRecordData;
import com.keepersecurity.secretsManager.core.KeeperRecordField;
import com.keepersecurity.secretsManager.core.KeyPair;
import com.keepersecurity.secretsManager.core.KeyPairs;
import com.keepersecurity.secretsManager.core.Login;
import com.keepersecurity.secretsManager.core.Password;
import com.keepersecurity.secretsManager.core.SecretsManager;
import com.keepersecurity.secretsManager.core.Text;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Future;
import java.util.function.Function;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Service for automatically parsing out secrets and data from Keeper records.
 */
@Singleton
public class KsmRecordService {

    /**
     * Regular expression which matches the labels of custom fields containing
     * hostnames/addresses.
     */
    private static final Pattern HOSTNAME_LABEL_PATTERN =
            Pattern.compile("hostname|(ip\\s*)?address", Pattern.CASE_INSENSITIVE);

    /**
     * Regular expression which matches the labels of custom fields containing
     * usernames.
     */
    private static final Pattern USERNAME_LABEL_PATTERN =
            Pattern.compile("username", Pattern.CASE_INSENSITIVE);

    /**
     * Regular expression which matches the labels of custom fields containing
     * passwords.
     */
    private static final Pattern PASSWORD_LABEL_PATTERN =
            Pattern.compile("password", Pattern.CASE_INSENSITIVE);

    /**
     * Regular expression which matches the labels of custom fields containing
     * passphrases for private keys.
     */
    private static final Pattern PASSPHRASE_LABEL_PATTERN =
            Pattern.compile("passphrase", Pattern.CASE_INSENSITIVE);

    /**
     * Regular expression which matches the labels of custom fields containing
     * private keys.
     */
    private static final Pattern PRIVATE_KEY_LABEL_PATTERN =
            Pattern.compile("private\\s*key", Pattern.CASE_INSENSITIVE);

    /**
     * Regular expression which matches the filenames of private keys attached
     * to Keeper records.
     */
    private static final Pattern PRIVATE_KEY_FILENAME_PATTERN =
            Pattern.compile(".*\\.pem", Pattern.CASE_INSENSITIVE);

    /**
     * Returns the single value stored in the given list. If the list is empty
     * or contains multiple values, null is returned. Note that null will also
     * be returned if the single value stored in the list is itself null.
     *
     * @param <T>
     *     The type of object stored in the list.
     *
     * @param values
     *     The list to retrieve a single value from.
     *
     * @return
     *     The single value stored in the given list, or null if the list is
     *     empty or contains multiple values.
     */
    private <T> T getSingleValue(List<T> values) {

        if (values == null || values.size() != 1)
            return null;

        return values.get(0);

    }

    /**
     * Returns the single value stored in the given list of strings. If the
     * list is empty, contains multiple values, or contains only a single empty
     * string, null is returned. Note that null will also be returned if the
     * single value stored in the list is itself null.
     *
     * @param values
     *     The list to retrieve a single value from.
     *
     * @return
     *     The single value stored in the given list, or null if the list is
     *     empty, contains multiple values, or contains only a single empty
     *     string.
     */
    private String getSingleStringValue(List<String> values) {

        String value = getSingleValue(values);
        if (value != null && !value.isEmpty())
            return value;

        return null;

    }

    /**
     * Returns the single value stored in the given list, additionally
     * performing a mapping transformation on the single value. If the list is
     * empty or contains multiple values, null is returned. Note that null will
     * also be returned if the mapping transformation returns null for the
     * single value stored in the list.
     * 
     * @param <T>
     *     The type of object stored in the list.
     *     
     * @param <R>
     *     The type of object to return.
     *     
     * @param values
     *     The list to retrieve a single value from.
     *
     * @param mapper
     *     The function to use to map the single object of type T to type R.
     *
     * @return
     *     The single value stored in the given list, transformed using the
     *     provided mapping function, or null if the list is empty or contains
     *     multiple values.
     */
    private <T, R> R getSingleValue(List<T> values, Function<T, R> mapper) {

        T value = getSingleValue(values);
        if (value == null)
            return null;

        return mapper.apply(value);
        
    }

    /**
     * Returns the single value stored in the given list of strings,
     * additionally performing a mapping transformation on the single value. If
     * the list is empty, contains multiple values, or contains only a single
     * empty string, null is returned. Note that null will also be returned if
     * the mapping transformation returns null for the single value stored in
     * the list.
     *
     * @param <T>
     *     The type of object stored in the list.
     *
     * @param values
     *     The list to retrieve a single value from.
     *
     * @param mapper
     *     The function to use to map the single object of type T to type R.
     *
     * @return
     *     The single value stored in the given list, transformed using the
     *     provided mapping function, or null if the list is empty, contains
     *     multiple values, or contains only a single empty string.
     */
    private <T> String getSingleStringValue(List<T> values, Function<T, String> mapper) {

        String value = getSingleValue(values, mapper);
        if (value != null && !value.isEmpty())
            return value;

        return null;

    }

    /**
     * Returns the instance of the only field that has the given type and
     * matches the given label pattern. If there are no such fields, or
     * multiple such fields, null is returned.
     *
     * @param <T>
     *     The type of field to return.
     *
     * @param fields
     *     The list of fields to retrieve the field from. For convenience, this
     *     may be null. A null list will be considered equivalent to an empty
     *     list.
     *
     * @param fieldClass
     *     The class representing the type of field to return.
     *
     * @param labelPattern
     *     The pattern to match against the desired field's label, or null if
     *     no label pattern match should be performed.
     *
     * @return
     *     The field having the given type and matching the given label
     *     pattern, or null if there is not exactly one such field.
     */
    @SuppressWarnings("unchecked") // Manually verified with isAssignableFrom()
    private <T extends KeeperRecordField> T getField(List<KeeperRecordField> fields,
            Class<T> fieldClass, Pattern labelPattern) {

        // There are no fields if no List was provided at all
        if (fields == null)
            return null;

        T foundField = null;
        for (KeeperRecordField field : fields) {

            // Ignore fields of wrong class
            if (!fieldClass.isAssignableFrom(field.getClass()))
                continue;

            // Match against provided pattern, if any
            if (labelPattern != null) {

                // Ignore fields without labels if a label match is requested
                String label = field.getLabel();
                if (label == null)
                    continue;

                // Ignore fields whose labels do not match
                Matcher labelMatcher = labelPattern.matcher(label);
                if (!labelMatcher.matches())
                    continue;

            }

            // Ignore ambiguous fields
            if (foundField != null)
                return null;

            // Tentative match found - we can use this as long as no other
            // field matches the criteria
            foundField = (T) field;

        }

        return foundField;

    }

    /**
     * Returns the instance of the only field that has the given type and
     * matches the given label pattern. If there are no such fields, or
     * multiple such fields, null is returned. Both standard and custom fields
     * are searched. As standard fields do not have labels, any given label
     * pattern is ignored for standard fields.
     * 
     * @param <T>
     *     The type of field to return.
     *
     * @param record
     *     The Keeper record to retrieve the field from.
     *
     * @param fieldClass
     *     The class representing the type of field to return.
     *
     * @param labelPattern
     *     The pattern to match against the labels of custom fields, or null if
     *     no label pattern match should be performed.
     *
     * @return
     *     The field having the given type and matching the given label
     *     pattern, or null if there is not exactly one such field.
     */
    private <T extends KeeperRecordField> T getField(KeeperRecord record,
            Class<T> fieldClass, Pattern labelPattern) {

        KeeperRecordData data = record.getData();

        // Attempt to find standard field first, ignoring custom fields if a
        // standard field exists (NOTE: standard fields do not have labels)
        T field = getField(data.getFields(), fieldClass, null);
        if (field != null)
            return field;

        // Fall back on custom fields
        return getField(data.getCustom(), fieldClass, labelPattern);

    }

    /**
     * Returns the file attached to the give Keeper record whose filename
     * matches the given pattern. If there are no such files, or multiple such
     * files, null is returned.
     *
     * @param record
     *     The record to retrieve the file from.
     *
     * @param filenamePattern
     *     The pattern to match filenames against.
     *
     * @return
     *     The single matching file attached to the given Keeper record, or
     *     null if there is not exactly one matching file.
     */
    private KeeperFile getFile(KeeperRecord record, Pattern filenamePattern) {

        List<KeeperFile> files = record.getFiles();
        if (files == null)
            return null;

        KeeperFile foundFile = null;
        for (KeeperFile file : files) {

            // Ignore files whose filenames do not match
            Matcher filenameMatcher = filenamePattern.matcher(file.getData().getName());
            if (!filenameMatcher.matches())
                continue;

            // Ignore ambiguous fields
            if (foundFile != null)
                return null;

            foundFile = file;
            
        }

        return foundFile;

    }

    /**
     * Downloads the given file from the Keeper vault asynchronously. All files
     * are read as UTF-8.
     *
     * @param file
     *     The file to download, which may be null.
     *
     * @return
     *     A Future which resolves with the contents of the file once
     *     downloaded. If no file was provided (file was null), this Future
     *     resolves with null.
     */
    public Future<String> download(final KeeperFile file) {

        if (file == null)
            return CompletableFuture.completedFuture(null);
        
        return CompletableFuture.supplyAsync(() -> {
            return new String(SecretsManager.downloadFile(file), StandardCharsets.UTF_8);
        });

    }

    /**
     * Returns the single hostname (or address) associated with the given
     * record. If the record has no associated hostname, or multiple hostnames,
     * null is returned. Hostnames are retrieved from "Hosts" fields, as well
     * as "Text" and "Hidden" fields that have the label "hostname", "address",
     * or "ip address" (case-insensitive, space optional).
     *
     * @param record
     *     The record to retrieve the hostname from.
     *
     * @return
     *     The hostname associated with the given record, or null if the record
     *     has no associated hostname or multiple hostnames.
     */
    public String getHostname(KeeperRecord record) {

        // Prefer standard login field
        Hosts hostsField = getField(record, Hosts.class, null);
        if (hostsField != null)
            return getSingleStringValue(hostsField.getValue(), Host::getHostName);

        KeeperRecordData data = record.getData();
        List<KeeperRecordField> custom = data.getCustom();

        // Use text "hostname" custom field as fallback ...
        Text textField = getField(custom, Text.class, HOSTNAME_LABEL_PATTERN);
        if (textField != null)
            return getSingleStringValue(textField.getValue());

        // ... or hidden "hostname" custom field
        HiddenField hiddenField = getField(custom, HiddenField.class, HOSTNAME_LABEL_PATTERN);
        if (hiddenField != null)
            return getSingleStringValue(hiddenField.getValue());

        return null;

    }

    /**
     * Returns the single username associated with the given record. If the
     * record has no associated username, or multiple usernames, null is
     * returned. Usernames are retrieved from "Login" fields, as well as
     * "Text" and "Hidden" fields that have the label "username"
     * (case-insensitive).
     *
     * @param record
     *     The record to retrieve the username from.
     *
     * @return
     *     The username associated with the given record, or null if the record
     *     has no associated username or multiple usernames.
     */
    public String getUsername(KeeperRecord record) {

        // Prefer standard login field
        Login loginField = getField(record, Login.class, null);
        if (loginField != null)
            return getSingleStringValue(loginField.getValue());

        KeeperRecordData data = record.getData();
        List<KeeperRecordField> custom = data.getCustom();

        // Use text "username" custom field as fallback ...
        Text textField = getField(custom, Text.class, USERNAME_LABEL_PATTERN);
        if (textField != null)
            return getSingleStringValue(textField.getValue());

        // ... or hidden "username" custom field
        HiddenField hiddenField = getField(custom, HiddenField.class, USERNAME_LABEL_PATTERN);
        if (hiddenField != null)
            return getSingleStringValue(hiddenField.getValue());

        return null;

    }

    /**
     * Returns the password associated with the given record. Both standard and
     * custom fields are searched. Only "Password" and "Hidden" field types are
     * considered. Custom fields must additionally have the label "password"
     * (case-insensitive).
     *
     * @param record
     *     The record to retrieve the password from.
     *
     * @return
     *     The password associated with the given record, or null if the record
     *     has no associated password.
     */
    public String getPassword(KeeperRecord record) {

        Password passwordField = getField(record, Password.class, PASSWORD_LABEL_PATTERN);
        if (passwordField != null)
            return getSingleStringValue(passwordField.getValue());

        HiddenField hiddenField = getField(record, HiddenField.class, PASSWORD_LABEL_PATTERN);
        if (hiddenField != null)
            return getSingleStringValue(hiddenField.getValue());

        return null;

    }

    /**
     * Returns the private key associated with the given record. If the record
     * has no associated private key, or multiple private keys, null is
     * returned. Private keys are retrieved from "KeyPairs" fields.
     * Alternatively, private keys are retrieved from PEM-type attachments or
     * custom fields with the label "private key" (case-insensitive, space
     * optional) if they are "KeyPairs", "Password", or "Hidden" fields. If
     * file downloads are required, they will be performed asynchronously.
     *
     * @param record
     *     The record to retrieve the private key from.
     *
     * @return
     *     A Future which resolves with the private key associated with the
     *     given record. If the record has no associated private key or
     *     multiple private keys, the returned Future will resolve to null.
     */
    public Future<String> getPrivateKey(KeeperRecord record) {

        // Attempt to find single matching keypair field
        KeyPairs keyPairsField = getField(record, KeyPairs.class, PRIVATE_KEY_LABEL_PATTERN);
        if (keyPairsField != null) {
            String privateKey = getSingleStringValue(keyPairsField.getValue(), KeyPair::getPrivateKey);
            if (privateKey != null && !privateKey.isEmpty())
                return CompletableFuture.completedFuture(privateKey);
        }

        // Lacking a typed keypair field, prefer a PEM-type attachment
        KeeperFile keyFile = getFile(record, PRIVATE_KEY_FILENAME_PATTERN);
        if (keyFile != null)
            return download(keyFile);

        KeeperRecordData data = record.getData();
        List<KeeperRecordField> custom = data.getCustom();

        // Use password "private key" custom field as fallback ...
        Password passwordField = getField(custom, Password.class, PRIVATE_KEY_LABEL_PATTERN);
        if (passwordField != null)
            return CompletableFuture.completedFuture(getSingleStringValue(passwordField.getValue()));

        // ... or hidden "private key" custom field
        HiddenField hiddenField = getField(custom, HiddenField.class, PRIVATE_KEY_LABEL_PATTERN);
        if (hiddenField != null)
            return CompletableFuture.completedFuture(getSingleStringValue(hiddenField.getValue()));

        return CompletableFuture.completedFuture(null);

    }

    /**
     * Returns the passphrase for the private key associated with the given
     * record. Both standard and custom fields are searched. Only "Password"
     * and "Hidden" field types are considered. Custom fields must additionally
     * have the label "passphrase" (case-insensitive). Note that there is no
     * specific association between private keys and passphrases in the
     * "KeyPairs" field type.
     *
     * @param record
     *     The record to retrieve the passphrase from.
     *
     * @return
     *     The passphrase for the private key associated with the given record,
     *     or null if there is no such passphrase associated with the record.
     */
    public String getPassphrase(KeeperRecord record) {

        KeeperRecordData data = record.getData();
        List<KeeperRecordField> fields = data.getFields();
        List<KeeperRecordField> custom = data.getCustom();

        // For records with a standard keypair field, the passphrase is the
        // standard password field
        if (getField(fields, KeyPairs.class, null) != null) {
            Password passwordField = getField(fields, Password.class, null);
            if (passwordField != null)
                return getSingleStringValue(passwordField.getValue());
        }

        // For records WITHOUT a standard keypair field, the passphrase can
        // only reasonably be a custom field (consider a "Login" record with
        // a pair of custom hidden fields for the private key and passphrase:
        // the standard password field of the "Login" record refers to the
        // user's own password, if any, not the passphrase of their key)
        
        // Use password "private key" custom field as fallback ...
        Password passwordField = getField(custom, Password.class, PASSPHRASE_LABEL_PATTERN);
        if (passwordField != null)
            return getSingleStringValue(passwordField.getValue());

        // ... or hidden "private key" custom field
        HiddenField hiddenField = getField(custom, HiddenField.class, PASSPHRASE_LABEL_PATTERN);
        if (hiddenField != null)
            return getSingleStringValue(hiddenField.getValue());

        return null;
        
    }

}
