using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Mozilla.CharDet;
using Ude;

namespace EncodeDetector
{
    public static class VtrEncodingDetector
    {
        /// <summary>
        /// Retorna encoding do streaming. (UTF7; UTF8; Unicode)
        /// </summary>
        /// <param name="stream">Bytes do Arquivo</param>
        /// <returns>Encoding Type</returns>
        public static Encoding GetEncodingFile(byte[] bytes)
        {
            if (bytes != null && bytes.Length >= 2)
            {
                //verifica esses primeiro pois utf32 pode confundir-se com utf16
                if (bytes[0] == 0xff && bytes[1] == 0xfe && bytes[2] == 0 && bytes[3] == 0)
                    return Encoding.UTF32;

                //utf-32BE  Unicode (UTF-32 Big-Endian)  
                if (bytes[0] == 0 && bytes[1] == 0 && bytes[2] == 0xfe && bytes[3] == 0xff)
                    return Encoding.GetEncoding(12001);

                if (bytes[0] == 255 && bytes[1] == 254)
                    return Encoding.Unicode;

                if (bytes[0] == 0xfe && bytes[1] == 0xff)
                    return Encoding.BigEndianUnicode;


                if (bytes[0] == 239 && bytes[1] == 187 && bytes[2] == 191)
                    return Encoding.UTF8;

                if (bytes[0] == 60 && bytes[1] == 63)
                    return Encoding.ASCII;

                //reconhecimento de utf7 http://pt.wikipedia.org/wiki/Marca_de_ordem_de_byte
                if (bytes[0] == 43 && bytes[1] == 47 && bytes[2] == 118 && (bytes[3] == 56 || bytes[3] == 57 || bytes[3] == 43 || bytes[3] == 47))
                    return Encoding.UTF7;

                //uso da ferramenta UDE para detectar automaticamente o encoding
                try
                {
                    //http://code.google.com/p/ude/
                    CharsetDetector d = new CharsetDetector();
                    d.Feed(bytes, 0, bytes.Length);
                    d.DataEnd();
                    Encoding enc = Encoding.GetEncoding(d.Charset);
                    d.Reset();
                    if (enc != null)
                        return enc;
                    else
                        //por padrão retorna 1252, que é o iso 8859-1, ansi para europa ocidental, codepage padrão para windows em inglês e português
                        //http://msdn.microsoft.com/en-us/library/system.text.encoding.codepage(v=vs.110).aspx
                        //return Encoding.GetEncoding(1252);
                        return Encoding.Default;
                }
                catch
                {
                    //por padrão retorna 1252, que é o iso 8859-1, ansi para europa ocidental, codepage padrão para windows em inglês e português
                    //http://msdn.microsoft.com/en-us/library/system.text.encoding.codepage(v=vs.110).aspx
                    //return Encoding.GetEncoding(1252);
                    return Encoding.Default;
                }
            }
            //por padrão retorna 1252, que é o iso 8859-1, ansi para europa ocidental, codepage padrão para windows em inglês e português
            //http://msdn.microsoft.com/en-us/library/system.text.encoding.codepage(v=vs.110).aspx
            //return Encoding.GetEncoding(1252);
            return Encoding.Default;
        }
    }
}
