#if !UNITY_WEBPLAYER

using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Globalization;
using System.Security.Cryptography;

namespace mgaia.Utils.Security
{
	/// <summary>
	/// Objeto processador de criptografia que utiliza um algortimo Rjindael (simétrico)
	/// </summary>
	/// <owner>Victor</owner>
	public class SymmetricCryptoProcessor : ICryptoProcessor
	{
		private const uint KEY_LENGTH = 32;
		private const uint VECTOR_LENGTH = 16;

		private AesManaged mCryptoMethod;

		public SymmetricCryptoProcessor(string key, string vector)
		{
			if (String.IsNullOrEmpty(key))
			{
				throw new ArgumentNullException("key");
			}

			if (key != null && key.Length != KEY_LENGTH)
			{
				throw new ArgumentException("A chave deve ter " + KEY_LENGTH + " caracteres!", "key");
			}

			if (vector != null && vector.Length != VECTOR_LENGTH)
			{
				throw new ArgumentException("O vector deve ter " + VECTOR_LENGTH + " caracteres!", "key");
			}

			mCryptoMethod = new AesManaged();
			mCryptoMethod.Key = Encoding.UTF8.GetBytes(key);
			mCryptoMethod.IV = Encoding.UTF8.GetBytes(vector);
		}

		public string Decrypt(string value)
		{
			try
			{
                using (ICryptoTransform decryptingTransform = mCryptoMethod.CreateDecryptor())
                {
                    byte[] encryptedValue = FromHexString(value);

                    using (MemoryStream msDecrypt = new MemoryStream(encryptedValue))
                    {
                        using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptingTransform, CryptoStreamMode.Read))
                        {
                            List<byte> bytes = new List<byte>();
                            int readByte;
                            while ((readByte = csDecrypt.ReadByte()) != -1)
                            {
                                bytes.Add((byte)readByte);
                            }

                            byte[] byteArray = bytes.ToArray();
                            return Encoding.UTF8.GetString(byteArray, 0, byteArray.Length);
                        }
                    }
                }
			}
			catch
			{
				throw new UnableToDecryptException(value);
			}
		}

		public string Encrypt(string value)
		{
            using (ICryptoTransform encryptingTransform = mCryptoMethod.CreateEncryptor())
            {
                using (MemoryStream msEncrypt = new MemoryStream())
                {
                    using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptingTransform, CryptoStreamMode.Write))
                    {
                        byte[] valueInByteArray = Encoding.UTF8.GetBytes(value);
                        csEncrypt.Write(valueInByteArray, 0, valueInByteArray.Length);
                        csEncrypt.FlushFinalBlock();

                        return ToHexString(msEncrypt.ToArray());
                    }
                }
            }
		}

		/// <summary>
		/// Transforma um array de bytes em uma string hexadecimal
		/// </summary>
		private string ToHexString(byte[] byteArray)
		{
			StringBuilder hexStringBuilder = new StringBuilder(byteArray.Length * 2);
			foreach (byte @byte in byteArray)
			{
				hexStringBuilder.AppendFormat("{0:x2}", @byte);
			}

			return hexStringBuilder.ToString();
		}

		/// <summary>
		/// Transforma uma string hexadecimal em um array de bytes
		/// </summary>
		private byte[] FromHexString(string hexString)
		{
			byte[] bytes = new byte[hexString.Length / 2];
			for (int i = 0; i < hexString.Length; i += 2)
				bytes[i / 2] = byte.Parse(hexString.Substring(i, 2), NumberStyles.HexNumber);
			return bytes;
		}
	}
}

#endif