/*
 * 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.auth.duo.api;

import java.io.UnsupportedEncodingException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.xml.bind.DatatypeConverter;
import org.apache.guacamole.GuacamoleClientException;
import org.apache.guacamole.GuacamoleException;

/**
 * Data which describes the identity of the user being verified by Duo.
 */
public class DuoCookie {

    /**
     * Pattern which matches valid cookies. Each cookie is made up of three
     * sections, separated from each other by pipe symbols ("|").
     */
    private static final Pattern COOKIE_FORMAT = Pattern.compile("([^|]+)\\|([^|]+)\\|([0-9]+)");

    /**
     * The index of the capturing group within COOKIE_FORMAT which contains the
     * username.
     */
    private static final int USERNAME_GROUP = 1;

    /**
     * The index of the capturing group within COOKIE_FORMAT which contains the
     * integration key.
     */
    private static final int INTEGRATION_KEY_GROUP = 2;

    /**
     * The index of the capturing group within COOKIE_FORMAT which contains the
     * expiration timestamp.
     */
    private static final int EXPIRATION_TIMESTAMP_GROUP = 3;

    /**
     * The username of the user being verified.
     */
    private final String username;

    /**
     * The integration key provided by Duo and specific to this deployment of
     * Guacamole.
     */
    private final String integrationKey;

    /**
     * The time that this cookie expires, in seconds since midnight of
     * 1970-01-01 (UTC).
     */
    private final long expires;

    /**
     * Creates a new DuoCookie which describes the identity of a user being
     * verified.
     *
     * @param username
     *     The username of the user being verified.
     *
     * @param integrationKey
     *     The integration key provided by Duo and specific to this deployment
     *     of Guacamole.
     *
     * @param expires
     *     The time that this cookie expires, in seconds since midnight of
     *     1970-01-01 (UTC).
     */
    public DuoCookie(String username, String integrationKey, long expires) {
        this.username = username;
        this.integrationKey = integrationKey;
        this.expires = expires;
    }

    /**
     * Returns the username of the user being verified.
     *
     * @return
     *     The username of the user being verified.
     */
    public String getUsername() {
        return username;
    }

    /**
     * Returns the integration key provided by Duo and specific to this
     * deployment of Guacamole.
     *
     * @return
     *     The integration key provided by Duo and specific to this deployment
     *     of Guacamole.
     */
    public String getIntegrationKey() {
        return integrationKey;
    }

    /**
     * Returns the time that this cookie expires. The expiration time is
     * represented in seconds since midnight of 1970-01-01 (UTC).
     *
     * @return
     *     The time that this cookie expires, in seconds since midnight of
     *     1970-01-01 (UTC).
     */
    public long getExpirationTimestamp(){
        return expires;
    }

    /**
     * Returns the current time as the number of seconds elapsed since
     * midnight of 1970-01-01 (UTC).
     *
     * @return
     *     The current time as the number of seconds elapsed since midnight of
     *     1970-01-01 (UTC).
     */
    public static long currentTimestamp() {
        return System.currentTimeMillis() / 1000;
    }

    /**
     * Returns whether this cookie has expired (the current time has met or
     * exceeded the expiration timestamp).
     *
     * @return
     *     true if this cookie has expired, false otherwise.
     */
    public boolean isExpired() {
        return currentTimestamp() >= expires;
    }

    /**
     * Parses a base64-encoded Duo cookie, producing a new DuoCookie object
     * containing the data therein. If the given string is not a valid Duo
     * cookie, an exception is thrown. Note that the cookie may be expired, and
     * must be checked for expiration prior to actual use.
     *
     * @param str
     *     The base64-encoded Duo cookie to parse.
     *
     * @return
     *     A new DuoCookie object containing the same data as the given
     *     base64-encoded Duo cookie string.
     *
     * @throws GuacamoleException
     *     If the given string is not a valid base64-encoded Duo cookie.
     */
    public static DuoCookie parseDuoCookie(String str) throws GuacamoleException {

        // Attempt to decode data as base64
        String data;
        try {
            data = new String(DatatypeConverter.parseBase64Binary(str), "UTF-8");
        }

        // Bail if invalid base64 is provided
        catch (IllegalArgumentException e) {
            throw new GuacamoleClientException("Username is not correctly "
                    + "encoded as base64.", e);
        }

        // Throw hard errors if standard pieces of Java are missing
        catch (UnsupportedEncodingException e) {
            throw new UnsupportedOperationException("Unexpected lack of "
                    + "UTF-8 support.", e);
        }

        // Verify format of provided data
        Matcher matcher = COOKIE_FORMAT.matcher(data);
        if (!matcher.matches())
            throw new GuacamoleClientException("Format of base64-encoded "
                    + "username is invalid.");

        // Get username and key (simple strings)
        String username = matcher.group(USERNAME_GROUP);
        String key = matcher.group(INTEGRATION_KEY_GROUP);

        // Parse expiration time
        long expires;
        try {
            expires = Long.parseLong(matcher.group(EXPIRATION_TIMESTAMP_GROUP));
        }

        // Bail if expiration timestamp is not a valid long
        catch (NumberFormatException e) {
            throw new GuacamoleClientException("Expiration timestamp is "
                    + "not valid.", e);
        }

        // Return parsed cookie
        return new DuoCookie(username, key, expires);

    }

    /**
     * Returns the base64-encoded string representation of this DuoCookie. The
     * format used is identical to that required by the Duo service: the
     * username, integration key, and expiration timestamp separated by pipe
     * symbols ("|") and encoded with base64.
     *
     * @return
     *     The base64-encoded string representation of this DuoCookie.
     */
    @Override
    public String toString() {

        try {

            // Separate each cookie field with pipe symbols
            String data = username + "|" + integrationKey + "|" + expires;

            // Encode resulting cookie string with base64
            return DatatypeConverter.printBase64Binary(data.getBytes("UTF-8"));

        }

        // Throw hard errors if standard pieces of Java are missing
        catch (UnsupportedEncodingException e) {
            throw new UnsupportedOperationException("Unexpected lack of UTF-8 support.", e);
        }

    }

}
