package org.jboss.resteasy.plugins.providers.multipart;

import org.jboss.resteasy.plugins.providers.multipart.i18n.LogMessages;
import org.jboss.resteasy.plugins.providers.multipart.i18n.Messages;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.UUID;

/**
 * Utility class to help generate, convert RFC compliant Content-ID and cid.
 * 
 * @author Attila Kiraly
 *
 */
public class ContentIDUtils {
	public static final String CID_URL_SCHEME = "cid:";

	/**
	 * Calls {@link #generateContentIDFromAddrSpec(String)} with
	 * {@link #generateRFC822AddrSpec()} as parameter.
	 * 
	 * @return the generated Content-ID
	 */
	public static String generateContentID() {
		return generateContentIDFromAddrSpec(generateRFC822AddrSpec());
	}

	/**
	 * Helper method to generate a standards-compliant Content-ID header value
	 * from the supplied addrSpec.
	 * 
	 * Used rfc-s: RFC2045, RFC822
	 * 
	 * @return the generated Content-ID
	 */
	public static String generateContentIDFromAddrSpec(String addrSpec) {
		return "<" + addrSpec + ">";
	}

	/**
	 * Helper method to generate a standards-compliant, random addr-spec as
	 * described in RFC822.
	 * 
	 * @return the generated addrSpec
	 */
	public static String generateRFC822AddrSpec() {
		return UUID.randomUUID().toString() + "@resteasy-multipart";
	}

	/**
	 * Helper method to generate a standards-compliant cid url from the supplied
	 * addrSpec. This implementation URL encodes everything without considering
	 * if it is needed or not.
	 * 
	 * Used rfc-s: RFC2392, RFC822
	 * 
	 * @return the generated Content-ID
	 */
	public static String generateCidFromAddrSpec(String addrSpec) {
		String cid = CID_URL_SCHEME;
		try {
			cid += URLEncoder.encode(addrSpec, StandardCharsets.UTF_8.name());
		} catch (UnsupportedEncodingException e) {
		   LogMessages.LOGGER.error(Messages.MESSAGES.urlEncoderDoesNotSupportUtf8(), e);
		}
		return cid;
	}

	/**
	 * @param cid
	 *            the RFC2392 compliant cid
	 * @return the RFC822 defined addr-spec decoded from the cid
	 */
	public static String parseAddrSpecFromCid(String cid) {
		String addrSpec = cid.trim();
		if (addrSpec.startsWith(CID_URL_SCHEME))
			addrSpec = addrSpec.substring(CID_URL_SCHEME.length()).trim();

		try {
			addrSpec = URLDecoder.decode(addrSpec, StandardCharsets.UTF_8.name());
		} catch (UnsupportedEncodingException e) {
		   LogMessages.LOGGER.error(Messages.MESSAGES.urlDecoderDoesNotSupportUtf8(), e);
		}

		return addrSpec;
	}

	/**
	 * @param contentID
	 *            the RFC2045 compliant Content-ID
	 * @return the RFC822 defined addr-spec decoded from the contentID
	 */
	public static String parseAddrSpecFromContentID(String contentID) {
		String addrSpec = contentID.trim();

		if (addrSpec.startsWith("<") && addrSpec.endsWith(">"))
			addrSpec = addrSpec.substring(1, addrSpec.length() - 1).trim();

		return addrSpec;
	}

	/**
	 * @param cid
	 *            the RFC2392 compliant cid
	 * @return the RFC2045 compliant Content-ID representing the cid
	 */
	public static String convertCidToContentID(String cid) {
		return generateContentIDFromAddrSpec(parseAddrSpecFromCid(cid));
	}

	/**
	 * @param contentID
	 *            the RFC2045 compliant Content-ID
	 * @return the RFC2392 compliant cid representing the contentID
	 */
	public static String convertContentIDToCid(String contentID) {
		return generateCidFromAddrSpec(parseAddrSpecFromContentID(contentID));
	}
}
