using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace skyscraper5.Skyscraper.Text.Encodings
{
    [SkyscraperEncoding("dvb-iso-8859-6")]
    class dvb_iso_8859_6 : SkyscraperBaseEncoding8
    {
        protected override char[] Decrypt(byte[] preprocessed)
        {
            StringBuilder resultBuilder = new StringBuilder();
            bool arabMode = false;
            for (int i = 0; i < preprocessed.Length; i++)
            {
                switch (preprocessed[i])
                {
                    case 0x00: break;   //Null
                    case 0x03: return resultBuilder.ToString().ToCharArray();  //End of Text
                    case 0x0a: resultBuilder.Append('\n'); break;
                    case 0x0d: resultBuilder.Append('\u0013'); break;   //Carriage return
                    case 0x10: break;   //Data Link Escape
                    case 0x12: break;   //Device Control 2
                    case 0x13: break;   //Device Control 3
                    case 0x20: resultBuilder.Append(' '); break;
                    case 0x21: resultBuilder.Append('!'); break;
                    case 0x22: resultBuilder.Append('\"'); break;
                    case 0x23: resultBuilder.Append('#'); break;
                    case 0x24: resultBuilder.Append('$'); break;
                    case 0x25: resultBuilder.Append(!arabMode ? '%' : '٪'); break;
                    case 0x26: resultBuilder.Append('&'); break;
                    case 0x27: resultBuilder.Append('\''); break;
                    case 0x28: resultBuilder.Append('('); break;
                    case 0x29: resultBuilder.Append(')'); break;
                    case 0x2b: resultBuilder.Append('+'); break;
                    case 0x2c: resultBuilder.Append(','); break;
                    case 0x2d: resultBuilder.Append('-'); break;
                    case 0x2e: resultBuilder.Append('.'); break;
                    case 0x2f: resultBuilder.Append('/'); break;
                    case 0x30: resultBuilder.Append(!arabMode ? '0' : '٠'); break;
                    case 0x31: resultBuilder.Append(!arabMode ? '1' : '١'); break;
                    case 0x32: resultBuilder.Append(!arabMode ? '2' : '٢'); break;
                    case 0x33: resultBuilder.Append(!arabMode ? '3' : '٣'); break;
                    case 0x34: resultBuilder.Append(!arabMode ? '4' : '٤'); break;
                    case 0x35: resultBuilder.Append(!arabMode ? '5' : '٥'); break;
                    case 0x36: resultBuilder.Append(!arabMode ? '6' : '٦'); break;
                    case 0x37: resultBuilder.Append(!arabMode ? '7' : '٧'); break;
                    case 0x38: resultBuilder.Append(!arabMode ? '8' : '٨'); break;
                    case 0x39: resultBuilder.Append(!arabMode ? '9' : '٩'); break;
                    case 0x3a: resultBuilder.Append(':'); break;
                    case 0x3b: resultBuilder.Append(';'); break;
                    case 0x3c: resultBuilder.Append('<'); break;
                    case 0x3f: resultBuilder.Append('?'); break;
                    case 0x40: resultBuilder.Append('@'); break;
                    case 0x41: resultBuilder.Append('A'); arabMode = false; break;
                    case 0x42: resultBuilder.Append('B'); arabMode = false; break;
                    case 0x43: resultBuilder.Append('C'); arabMode = false; break;
                    case 0x44: resultBuilder.Append('D'); arabMode = false; break;
                    case 0x45: resultBuilder.Append('E'); arabMode = false; break;
                    case 0x46: resultBuilder.Append('F'); arabMode = false; break;
                    case 0x47: resultBuilder.Append('G'); arabMode = false; break;
                    case 0x48: resultBuilder.Append('H'); arabMode = false; break;
                    case 0x49: resultBuilder.Append('I'); arabMode = false; break;
                    case 0x4a: resultBuilder.Append('J'); arabMode = false; break;
                    case 0x4b: resultBuilder.Append('K'); arabMode = false; break;
                    case 0x4c: resultBuilder.Append('L'); arabMode = false; break;
                    case 0x4d: resultBuilder.Append('M'); arabMode = false; break;
                    case 0x4e: resultBuilder.Append('N'); arabMode = false; break;
                    case 0x4f: resultBuilder.Append('O'); arabMode = false; break;
                    case 0x50: resultBuilder.Append('P'); arabMode = false; break;
                    case 0x51: resultBuilder.Append('Q'); arabMode = false; break;
                    case 0x52: resultBuilder.Append('R'); arabMode = false; break;
                    case 0x53: resultBuilder.Append('S'); arabMode = false; break;
                    case 0x54: resultBuilder.Append('T'); arabMode = false; break;
                    case 0x55: resultBuilder.Append('U'); arabMode = false; break;
                    case 0x56: resultBuilder.Append('V'); arabMode = false; break;
                    case 0x57: resultBuilder.Append('W'); arabMode = false; break;
                    case 0x58: resultBuilder.Append('X'); arabMode = false; break;
                    case 0x59: resultBuilder.Append('Y'); arabMode = false; break;
                    case 0x5a: resultBuilder.Append('Z'); arabMode = false; break;
                    case 0x61: resultBuilder.Append('a'); arabMode = false; break;
                    case 0x62: resultBuilder.Append('b'); arabMode = false; break;
                    case 0x63: resultBuilder.Append('c'); arabMode = false; break;
                    case 0x64: resultBuilder.Append('d'); arabMode = false; break;
                    case 0x65: resultBuilder.Append('e'); arabMode = false; break;
                    case 0x66: resultBuilder.Append('f'); arabMode = false; break;
                    case 0x67: resultBuilder.Append('g'); arabMode = false; break;
                    case 0x68: resultBuilder.Append('h'); arabMode = false; break;
                    case 0x69: resultBuilder.Append('i'); arabMode = false; break;
                    case 0x6a: resultBuilder.Append('j'); arabMode = false; break;
                    case 0x6b: resultBuilder.Append('k'); arabMode = false; break;
                    case 0x6c: resultBuilder.Append('l'); arabMode = false; break;
                    case 0x6d: resultBuilder.Append('m'); arabMode = false; break;
                    case 0x6e: resultBuilder.Append('n'); arabMode = false; break;
                    case 0x6f: resultBuilder.Append('o'); arabMode = false; break;
                    case 0x70: resultBuilder.Append('p'); arabMode = false; break;
                    case 0x71: resultBuilder.Append('q'); arabMode = false; break;
                    case 0x72: resultBuilder.Append('r'); arabMode = false; break;
                    case 0x73: resultBuilder.Append('s'); arabMode = false; break;
                    case 0x74: resultBuilder.Append('t'); arabMode = false; break;
                    case 0x75: resultBuilder.Append('u'); arabMode = false; break;
                    case 0x76: resultBuilder.Append('v'); arabMode = false; break;
                    case 0x77: resultBuilder.Append('w'); arabMode = false; break;
                    case 0x78: resultBuilder.Append('x'); arabMode = false; break;
                    case 0x79: resultBuilder.Append('y'); arabMode = false; break;
                    case 0x7a: resultBuilder.Append('z'); arabMode = false; break;
                    case 0xa0: resultBuilder.Append('\u00a0'); break;
                    case 0xa4: resultBuilder.Append('\u00a4'); break;
                    case 0xac: resultBuilder.Append('،'); arabMode = true; break;
                    case 0xb2: break;
                    case 0xbb: resultBuilder.Append('؛'); arabMode = true; break;
                    case 0xbf: resultBuilder.Append('؟'); arabMode = true; break;
                    case 0xc1: resultBuilder.Append('ء'); arabMode = true; break;
                    case 0xc2: resultBuilder.Append('آ'); arabMode = true; break;
                    case 0xc3: resultBuilder.Append('أ'); arabMode = true; break;
                    case 0xc4: resultBuilder.Append('ؤ'); arabMode = true; break;
                    case 0xc5: resultBuilder.Append('إ'); arabMode = true; break;
                    case 0xc6: resultBuilder.Append('ئ'); arabMode = true; break;
                    case 0xc7: resultBuilder.Append('ا'); arabMode = true; break;
                    case 0xc8: resultBuilder.Append('ب'); arabMode = true; break;
                    case 0xc9: resultBuilder.Append('ة'); arabMode = true; break;
                    case 0xca: resultBuilder.Append('ت'); arabMode = true; break;
                    case 0xcb: resultBuilder.Append('ث'); arabMode = true; break;
                    case 0xcc: resultBuilder.Append('ج'); arabMode = true; break;
                    case 0xcd: resultBuilder.Append('ح'); arabMode = true; break;
                    case 0xce: resultBuilder.Append('خ'); arabMode = true; break;
                    case 0xcf: resultBuilder.Append('د'); arabMode = true; break;
                    case 0xd0: resultBuilder.Append('ذ'); arabMode = true; break;
                    case 0xd1: resultBuilder.Append('ر'); arabMode = true; break;
                    case 0xd2: resultBuilder.Append('ز'); arabMode = true; break;
                    case 0xd3: resultBuilder.Append('آ'); arabMode = true; break;
                    case 0xd4: resultBuilder.Append('ش'); arabMode = true; break;
                    case 0xd5: resultBuilder.Append('ص'); arabMode = true; break;
                    case 0xd6: resultBuilder.Append('ض'); arabMode = true; break;
                    case 0xd7: resultBuilder.Append('ط'); arabMode = true; break;
                    case 0xd8: resultBuilder.Append('ظ'); arabMode = true; break;
                    case 0xd9: resultBuilder.Append('ع'); arabMode = true; break;
                    case 0xda: resultBuilder.Append('غ'); arabMode = true; break;
                    case 0xdb: resultBuilder.Append('؛'); arabMode = true; break;
                    case 0xdd: break;   //doesn't seem to be mapped?
                    case 0xe0: resultBuilder.Append('ـ'); arabMode = true; break;
                    case 0xe1: resultBuilder.Append('ف'); arabMode = true; break;
                    case 0xe2: resultBuilder.Append('ق'); arabMode = true; break;
                    case 0xe3: resultBuilder.Append('ك'); arabMode = true; break;
                    case 0xe4: resultBuilder.Append('ل'); arabMode = true; break;
                    case 0xe5: resultBuilder.Append('م'); arabMode = true; break;
                    case 0xe6: resultBuilder.Append('ن'); arabMode = true; break;
                    case 0xe7: resultBuilder.Append('ه'); arabMode = true; break;
                    case 0xe8: resultBuilder.Append('و'); arabMode = true; break;
                    case 0xe9: resultBuilder.Append('ى'); arabMode = true; break;
                    case 0xea: resultBuilder.Append('ي'); arabMode = true; break;
                    case 0xeb: resultBuilder.Append('\u064b'); arabMode = true; break;
                    case 0xec: resultBuilder.Append('\u064c'); arabMode = true; break;
                    case 0xed: resultBuilder.Append('\u064d'); arabMode = true; break;
                    case 0xee: resultBuilder.Append('\u064e'); arabMode = true; break;
                    case 0xef: resultBuilder.Append('\u064f'); arabMode = true; break;
                    case 0xf0: resultBuilder.Append('\u0650'); arabMode = true; break;
                    case 0xf1: resultBuilder.Append('\u0651'); arabMode = true; break;
                    case 0xf2: resultBuilder.Append('\u0652'); arabMode = true; break;
                    case 0xfb: break;
                    case 0xfc: break;
                    default:
                        throw new NotImplementedException(String.Format("0x{0:X2}", preprocessed[i]));
                }
            }

            return resultBuilder.ToString().ToCharArray();
        }
    }
}
