/*-
 * ~~~~~~licensing~~~~~~
 * htpasswd
 * ==========
 * Copyright (C) 2020 - 2021 EmDev LLC
 * ==========
 * Licensed 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.
 * ~~~~~~/licensing~~~~~~
 */
package ru.entaxy.esb.system.auth.basic.htpasswd.entity;

import org.apache.commons.codec.binary.Base64;
import ru.entaxy.esb.system.auth.basic.jpa.api.entity.field.EncryptionAlgorithm;

import java.nio.charset.StandardCharsets;
import java.security.NoSuchAlgorithmException;

public class HtpasswdEntry {

    private static final String APR1_PREFIX = "$apr1$";
    private static final String SHA512_PREFIX = "$6$";
    private static final String SALTED_SHA1_PREFIX = "{SSHA}";
    private static final String PLAIN_PREFIX = "{PLAIN}";

    private static final String COLON = ":";
    private final String resultLine;

    public HtpasswdEntry(String login, String passwordHash, String salt, String encryptionAlgorithm) throws NoSuchAlgorithmException {
        this(login, passwordHash, salt, encryptionAlgorithm, true);
    }

    public HtpasswdEntry(String login, String passwordHash, String salt, String encryptionAlgorithm, boolean addLineSeparator) throws NoSuchAlgorithmException {
        StringBuilder content = new StringBuilder();
        content.append(login).append(COLON);

        if (EncryptionAlgorithm.MD5.equalsName(encryptionAlgorithm)) {
            content
                    .append(APR1_PREFIX)
                    .append(salt)
                    .append("$")
                    .append(passwordHash);
        } else if (EncryptionAlgorithm.SHA1.equalsName(encryptionAlgorithm)) {
            content.append(SALTED_SHA1_PREFIX);
            byte[] digest = Base64.decodeBase64(passwordHash);
            byte[] saltBytes = salt.getBytes(StandardCharsets.UTF_8);

            int l1 = digest.length;
            int l2 = saltBytes.length;
            byte[] resultArr = new byte[l1 + l2];
            System.arraycopy(digest, 0, resultArr, 0, l1);
            System.arraycopy(saltBytes, 0, resultArr, l1, l2);

            content.append(Base64.encodeBase64String(resultArr));
        } else if (EncryptionAlgorithm.SHA512.equalsName(encryptionAlgorithm)) {
            content
                    .append(SHA512_PREFIX)
                    .append(salt)
                    .append("$")
                    .append(passwordHash);
        } else if (EncryptionAlgorithm.PLAIN.equalsName(encryptionAlgorithm)) {
            content
                    .append(PLAIN_PREFIX)
                    .append(passwordHash);
        } else {
            content.append(passwordHash);
        }
        content.append(System.lineSeparator());

        this.resultLine = content.toString();
    }

    @Override
    public String toString() {
        return resultLine;
    }
}
