/*
 * 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.totp.form;

import com.google.common.io.BaseEncoding;
import com.google.inject.Inject;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.WriterException;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.QRCodeWriter;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.URI;
import javax.ws.rs.core.UriBuilder;
import javax.xml.bind.DatatypeConverter;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.auth.totp.user.UserTOTPKey;
import org.apache.guacamole.auth.totp.conf.ConfigurationService;
import org.apache.guacamole.form.Field;
import org.apache.guacamole.totp.TOTPGenerator;
import org.codehaus.jackson.annotate.JsonProperty;

/**
 * Field which prompts the user for an authentication code generated via TOTP.
 */
public class AuthenticationCodeField extends Field {

    /**
     * The name of the HTTP parameter which will contain the TOTP code provided
     * by the user to verify their identity.
     */
    public static final String PARAMETER_NAME = "guac-totp";

    /**
     * The unique name associated with this field type.
     */
    private static final String FIELD_TYPE_NAME = "GUAC_TOTP_CODE";

    /**
     * The width of QR codes to generate, in pixels.
     */
    private static final int QR_CODE_WIDTH = 256;

    /**
     * The height of QR codes to generate, in pixels.
     */
    private static final int QR_CODE_HEIGHT = 256;

    /**
     * BaseEncoding which encodes/decodes base32.
     */
    private static final BaseEncoding BASE32 = BaseEncoding.base32();

    /**
     * Service for retrieving configuration information.
     */
    @Inject
    private ConfigurationService confService;

    /**
     * The TOTP key to expose to the user for the sake of enrollment, if any.
     * If no such key should be exposed to the user, this will be null.
     */
    private UserTOTPKey key;

    /**
     * Creates a new field which prompts the user for an authentication code
     * generated via TOTP. The user's TOTP key is not exposed for enrollment.
     */
    public AuthenticationCodeField() {
        super(PARAMETER_NAME, FIELD_TYPE_NAME);
    }

    /**
     * Exposes the given key to facilitate enrollment.
     *
     * @param key
     *     The TOTP key to expose to the user for the sake of enrollment.
     */
    public void exposeKey(UserTOTPKey key) {
        this.key = key;
    }

    /**
     * Returns the username of the user associated with the key being used to
     * generate TOTP codes. If the user's key is not being exposed to facilitate
     * enrollment, this value will not be exposed either.
     *
     * @return
     *     The username of the user associated with the key being used to
     *     generate TOTP codes, or null if the user's key is not being exposed
     *     to facilitate enrollment.
     */
    public String getUsername() {

        // Do not reveal TOTP mode unless enrollment is in progress
        if (key == null)
            return null;

        return key.getUsername();

    }

    /**
     * Returns the base32-encoded secret key that is being used to generate TOTP
     * codes for the authenticating user. If the user's key is not being exposed
     * to facilitate enrollment, this value will not be exposed either.
     *
     * @return
     *     The base32-encoded secret key that is being used to generate TOTP
     *     codes for the authenticating user, or null if the user's key is not
     *     being exposed to facilitate enrollment.
     */
    public String getSecret() {

        // Do not reveal TOTP mode unless enrollment is in progress
        if (key == null)
            return null;

        return BASE32.encode(key.getSecret());

    }

    /**
     * Returns the number of digits used for each TOTP code. If the user's key
     * is not being exposed to facilitate enrollment, this value will not be
     * exposed either.
     *
     * @return
     *     The number of digits used for each TOTP code, or null if the user's
     *     key is not being exposed to facilitate enrollment.
     *
     * @throws GuacamoleException
     *     If the number of digits cannot be read from guacamole.properties.
     */
    public Integer getDigits() throws GuacamoleException {

        // Do not reveal code size unless enrollment is in progress
        if (key == null)
            return null;

        return confService.getDigits();
        
    }

    /**
     * Returns the human-readable name of the entity issuing user accounts. If
     * the user's key is not being exposed to facilitate enrollment, this value
     * will not be exposed either.
     *
     * @return
     *     The human-readable name of the entity issuing user accounts, or null
     *     if the user's key is not being exposed to facilitate enrollment.
     *
     * @throws GuacamoleException
     *     If the issuer cannot be read from guacamole.properties.
     */
    public String getIssuer() throws GuacamoleException {

        // Do not reveal code issuer unless enrollment is in progress
        if (key == null)
            return null;

        return confService.getIssuer();

    }

    /**
     * Returns the mode that TOTP code generation is operating in. This value
     * will be one of "SHA1", "SHA256", or "SHA512". If the user's key is not
     * being exposed to facilitate enrollment, this value will not be exposed
     * either.
     *
     * @return
     *     The mode that TOTP code generation is operating in, such as "SHA1",
     *     "SHA256", or "SHA512", or null if the user's key is not being
     *     exposed to facilitate enrollment.
     *
     * @throws GuacamoleException
     *     If the TOTP mode cannot be read from guacamole.properties.
     */
    public TOTPGenerator.Mode getMode() throws GuacamoleException {

        // Do not reveal TOTP mode unless enrollment is in progress
        if (key == null)
            return null;

        return confService.getMode();

    }

    /**
     * Returns the number of seconds that each TOTP code remains valid. If the
     * user's key is not being exposed to facilitate enrollment, this value will
     * not be exposed either.
     *
     * @return
     *     The number of seconds that each TOTP code remains valid, or null if
     *     the user's key is not being exposed to facilitate enrollment.
     *
     * @throws GuacamoleException
     *     If the period cannot be read from guacamole.properties.
     */
    public Integer getPeriod() throws GuacamoleException {

        // Do not reveal code period unless enrollment is in progress
        if (key == null)
            return null;

        return confService.getPeriod();

    }

    /**
     * Returns the "otpauth" URI for the secret key used to generate TOTP codes
     * for the current user. If the secret key is not being exposed to
     * facilitate enrollment, null is returned.
     *
     * @return
     *     The "otpauth" URI for the secret key used to generate TOTP codes
     *     for the current user, or null is the secret ket is not being exposed
     *     to facilitate enrollment.
     *
     * @throws GuacamoleException
     *     If the configuration information required for generating the key URI
     *     cannot be read from guacamole.properties.
     */
    @JsonProperty("keyUri")
    public URI getKeyURI() throws GuacamoleException {

        // Do not generate a key URI if no key is being exposed
        if (key == null)
            return null;

        // Format "otpauth" URL (see https://github.com/google/google-authenticator/wiki/Key-Uri-Format)
        String issuer = confService.getIssuer();
        return UriBuilder.fromUri("otpauth://totp/")
                .path(issuer + ":" + key.getUsername())
                .queryParam("secret", BASE32.encode(key.getSecret()))
                .queryParam("issuer", issuer)
                .queryParam("algorithm", confService.getMode())
                .queryParam("digits", confService.getDigits())
                .queryParam("period", confService.getPeriod())
                .build();

    }

    /**
     * Returns the URL of a QR code describing the user's TOTP key and
     * configuration. If the key is not being exposed for enrollment, null is
     * returned.
     *
     * @return 
     *     The URL of a QR code describing the user's TOTP key and
     *     configuration, or null if the key is not being exposed for
     *     enrollment.
     *
     * @throws GuacamoleException
     *     If the configuration information required for generating the QR code
     *     cannot be read from guacamole.properties.
     */
    @JsonProperty("qrCode")
    public String getQRCode() throws GuacamoleException {

        // Do not generate a QR code if no key is being exposed
        URI keyURI = getKeyURI();
        if (keyURI == null)
            return null;

        ByteArrayOutputStream stream = new ByteArrayOutputStream();

        try {

            // Create QR code writer
            QRCodeWriter writer = new QRCodeWriter();
            BitMatrix matrix = writer.encode(keyURI.toString(),
                    BarcodeFormat.QR_CODE, QR_CODE_WIDTH, QR_CODE_HEIGHT);

            // Produce PNG image of TOTP key text
            MatrixToImageWriter.writeToStream(matrix, "PNG", stream);

        }
        catch (WriterException e) {
            throw new IllegalArgumentException("QR code could not be "
                    + "generated for TOTP key.", e);
        }
        catch (IOException e) {
            throw new IllegalStateException("Image stream of QR code could "
                    + "not be written.", e);
        }

        // Return data URI for generated image
        return "data:image/png;base64,"
                + DatatypeConverter.printBase64Binary(stream.toByteArray());

    }

}
