/*
 * Copyright 2014 gitblit.com.
 *
 * 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.
 */
package com.gitblit.transport.ssh;

import java.io.Serializable;
import java.security.PublicKey;
import java.util.Arrays;
import java.util.List;

import org.apache.commons.codec.binary.Base64;
import org.apache.sshd.common.SshException;
import org.apache.sshd.common.util.buffer.Buffer;
import org.apache.sshd.common.util.buffer.ByteArrayBuffer;
import org.eclipse.jgit.lib.Constants;

import com.gitblit.Constants.AccessPermission;
import com.gitblit.utils.StringUtils;
import com.google.common.base.Joiner;

/**
 * Class that encapsulates a public SSH key and it's metadata.
 *
 * @author James Moger
 *
 */
public class SshKey implements Serializable {

	private static final long serialVersionUID = 1L;

	private String rawData;

	private PublicKey publicKey;

	private String comment;

	private String fingerprint;

	private String toString;

	private AccessPermission permission;

	public SshKey(String data) {
		// strip out line breaks (issue-571)
		this.rawData = Joiner.on("").join(data.replace("\r\n", "\n").split("\n"));
		this.permission = AccessPermission.PUSH;
	}

	public SshKey(PublicKey key) {
		this.publicKey = key;
		this.comment = "";
		this.permission = AccessPermission.PUSH;
	}

	public PublicKey getPublicKey() {
		if (publicKey == null && rawData != null) {
			// instantiate the public key from the raw key data
			final String[] parts = rawData.split(" ", 3);
			if (comment == null && parts.length == 3) {
				comment = parts[2];
			}
			final byte[] bin = Base64.decodeBase64(Constants.encodeASCII(parts[1]));
			try {
				publicKey = new ByteArrayBuffer(bin).getRawPublicKey();
			} catch (SshException e) {
				throw new RuntimeException(e);
			}
		}
		return publicKey;
	}

	public String getAlgorithm() {
		return getPublicKey().getAlgorithm();
	}

	public String getComment() {
		if (comment == null && rawData != null) {
			// extract comment from the raw data
			final String[] parts = rawData.split(" ", 3);
			if (parts.length == 3) {
				comment = parts[2];
			}
		}
		return comment;
	}

	public void setComment(String comment) {
		this.comment = comment;
		if (rawData != null) {
			rawData = null;
		}
	}

	/**
	 * Returns true if this key may be used to clone or fetch.
	 *
	 * @return true if this key can be used to clone or fetch
	 */
	public boolean canClone() {
		return permission.atLeast(AccessPermission.CLONE);
	}

	/**
	 * Returns true if this key may be used to push changes.
	 *
	 * @return true if this key can be used to push changes
	 */
	public boolean canPush() {
		return permission.atLeast(AccessPermission.PUSH);
	}

	/**
	 * Returns the access permission for the key.
	 *
	 * @return the access permission for the key
	 */
	public AccessPermission getPermission() {
		return permission;
	}

	/**
	 * Control the access permission assigned to this key.
	 *
	 * @param value
	 */
	public void setPermission(AccessPermission value) throws IllegalArgumentException {
		List<AccessPermission> permitted = Arrays.asList(AccessPermission.SSHPERMISSIONS);
		if (!permitted.contains(value)) {
			throw new IllegalArgumentException("Illegal SSH public key permission specified: " + value);
		}
		this.permission = value;
	}

	public String getRawData() {
		if (rawData == null && publicKey != null) {
			// build the raw data manually from the public key
			Buffer buf = new ByteArrayBuffer();

			// 1: identify the algorithm
			buf.putRawPublicKey(publicKey);
			String alg = buf.getString();

			// 2: encode the key
			buf.clear();
			buf.putPublicKey(publicKey);
			String b64 = Base64.encodeBase64String(buf.getBytes());

			String c = getComment();
			rawData = alg + " " + b64 + (StringUtils.isEmpty(c) ? "" : (" " + c));
		}
		return rawData;
	}

	public String getFingerprint() {
		if (fingerprint == null) {
			StringBuilder sb = new StringBuilder();
			// append the key hash as colon-separated pairs
			String hash;
			if (rawData != null) {
				final String[] parts = rawData.split(" ", 3);
				final byte [] bin = Base64.decodeBase64(Constants.encodeASCII(parts[1]));
				hash = StringUtils.getMD5(bin);
			} else {
				// TODO calculate the correct hash from a PublicKey instance
				hash = StringUtils.getMD5(getPublicKey().getEncoded());
			}
			for (int i = 0; i < hash.length(); i += 2) {
				sb.append(hash.charAt(i)).append(hash.charAt(i + 1)).append(':');
			}
			sb.setLength(sb.length() - 1);
			fingerprint = sb.toString();
		}
		return fingerprint;
	}

	@Override
	public boolean equals(Object o) {
		if (o instanceof PublicKey) {
			return getPublicKey().equals(o);
		} else if (o instanceof SshKey) {
			return getPublicKey().equals(((SshKey) o).getPublicKey());
		}
		return false;
	}

	@Override
	public int hashCode() {
		return getPublicKey().hashCode();
	}

	@Override
	public String toString() {
		if (toString == null) {
			StringBuilder sb = new StringBuilder();
			// TODO append the keysize
			int keySize = 0;
			if (keySize > 0) {
				sb.append(keySize).append(' ');
			}
			// append fingerprint
			sb.append(' ');
			sb.append(getFingerprint());
			// append the comment
			String c = getComment();
			if (!StringUtils.isEmpty(c)) {
				sb.append(' ');
				sb.append(c);
			}
			// append algorithm
			String alg = getAlgorithm();
			if (!StringUtils.isEmpty(alg)) {
				sb.append(" (").append(alg).append(")");
			}
			toString = sb.toString();
		}
		return toString;
	}
}
