using System;
using System.Collections.Generic;
using System.Text;
using everdrive3x.Rom;
using everdrive3x.Hardware;
using everdrive3x.Misc;
using System.IO;

namespace everdrive3x
{
    class ToolBox
    {
        Form1 main;

        private ToolBox() { }
       

        public ToolBox(Form1 form)
        {
            main = form;
        }

        public void readHeader()
        {
            main.lockInterface(true, true);
            main.addToConsole("---------------------------------------------------");
            try
            {
                Device d = Device.searchDevice();
                RomInterface rom = RomHeader.getHeader(d);
                main.addToConsole("ROM platform: " + rom.Platform);
                main.addToConsole("ROM name: " + rom.Name);
                main.addToConsole("ROM size: " + rom.DeclaratedSize / 1024 + "kb");
                main.addToConsole("ROM region: " + rom.Region);
                d.close();
            }
            catch (Exception x)
            {
                main.addToConsole("ERROR: " + x.Message);
            }
            main.lockInterface(false);
        }

        public void cleadPort()
        {
            main.lockInterface(true, true);
            String[] port_list = System.IO.Ports.SerialPort.GetPortNames();
            byte[] buff = new byte[Communication.BUFF_SIZE];
            main.addToConsole("---------------------------------------------------");
            for (int i = 0; i < port_list.Length; i++)
            {
                try
                {
                    System.IO.Ports.SerialPort port = new System.IO.Ports.SerialPort(port_list[i]);
                    port.Open();
                    port.WriteTimeout = 200;
                    port.ReadTimeout = 200;
                    port.Write(buff, 0, buff.Length);
                    System.Threading.Thread.Sleep(300);
                    port.Close();
                }
                catch (Exception) { }
            }

            try
            {
                Device d = Device.searchDevice();
                main.addToConsole("OK: device detected");
                d.close();
            }
            catch (Exception x)
            {
                main.addToConsole("ERROR: " + x.Message);
            }
            main.lockInterface(false);
        }

        public void detectDevice()
        {
            try
            {
                main.addToConsole("---------------------------------------------------");
                main.lockInterface(true,true);
                Device device = Device.searchDevice();
                main.addToConsole("DEVICE name: " + device.Profile.Name);
                main.addToConsole("DEVICE platform: " + device.Profile.PlatformName);
                main.addToConsole("DEVICE firmware: " + device.Profile.FirmwareVersion);
                main.addToConsole("DEVICE memory: " + device.Profile.MemorySize / 1048576 + "mb");
                main.addToConsole("DEVICE multigame support: " + device.Profile.MultiGameSupport);

                device.close();
            }
            catch (Exception x)
            {
                main.addToConsole("ERROR: " + x.Message);
            }
            main.lockInterface(false);
        }

        public void readEeprom()
        {
            
            try
            {
                main.addToConsole("---------------------------------------------------");
                main.lockInterface(true, true);
                int lines = 16;
                int columns = 16;
                byte[] buff = new byte[columns * lines];
                Device device = Device.searchDevice();
                for (int i = 0; i < buff.Length; i++) buff[i] = (byte)device.Control.readEeprom(i);
                device.close();

                for (int i = 0; i < lines; i++)
                {
                    main.addToConsole(BitConverter.ToString(buff, i * columns, columns));
                }
                    

            }
            catch (Exception x)
            {
                main.addToConsole("ERROR: " + x.Message);
            }
            main.lockInterface(false);

        }

        public void eraseFlash()
        {
            try
            {
                main.lockInterface(true, true);
                main.addToConsole("---------------------------------------------------");
                main.addToConsole("search device...");
                Device device = Device.searchDevice();
                main.addToConsole("OK: device detected");
                main.addToConsole("erasing...");
                try
                {
                    device.Control.erase();
                }
                catch (Exception)
                {
                    device.Control.eraseAuto(device.Profile.MemorySize);
                }
                device.close();
                main.addToConsole("erasig done");
            }
            catch (Exception x)
            {
                main.addToConsole("ERROR: " + x.Message);
            }
            main.lockInterface(false);
        }


        public void resetDevice()
        {
            try
            {
                main.lockInterface(true, true);
                main.addToConsole("---------------------------------------------------");
                main.addToConsole("search device...");
                Device device = Device.searchDevice();
                main.addToConsole("OK: device detected");
                main.addToConsole("reset...");
                device.Control.reset();
                device.close();
                main.addToConsole("OK");
            }
            catch (Exception x)
            {
                main.addToConsole("ERROR: " + x.Message);
            }
            main.lockInterface(false);
        }

        public void updateFirmware()
        {

            main.lockInterface(true, true);
            main.addToConsole("---------------------------------------------------");

            
            try
            {
                
                HexFile hex = HexFile.makeFromHexFile(main.openFileDialog_hex.FileName);
                main.addToConsole("search bootloader...");
                Device d = null;
                try
                {
                    d = Device.searchBootLoader();
                }
                catch (Exception)
                {
                    d = Device.searchDevice();
                    try { d.Control.reset(); }
                    catch (Exception) { }
                    d.close();
                    d = null;
                }
                if (d == null) d = Device.searchBootLoader();
                main.addToConsole("OK: bootloader detected");
                main.addToConsole("bootloader version: "+d.Profile.FirmwareVersion);
                int app_end = d.Control.bootAppEnd();
                int page_size = d.Control.bootPageSize();
                main.addToConsole("app end: " + app_end);
                main.addToConsole("page size: " + page_size);

                main.addToConsole("enter program mode");
                d.Control.bootEnterProgMode();
                main.addToConsole("erase...");
                d.Control.bootErase();
                main.addToConsole("start programming...");
                byte[] buff = hex.toBinary();
                if (buff.Length % page_size != 0)
                {
                    buff = new byte[buff.Length + buff.Length % page_size];
                    System.Array.Copy(hex.toBinary(), 0, buff, 0, hex.toBinary().Length);
                }
                d.Control.setAddr(0);

                for (int i = 0; i < buff.Length / page_size && i * page_size < app_end; i++)
                {
                    d.Control.bootWritePage(buff, i * page_size, page_size);
                }

                d.close();
                main.addToConsole("OK: programming done");

            }
            catch (Exception x)
            {
                main.addToConsole("ERROR: " + x.Message);
            }
            main.lockInterface(false);
        }


        public void readFirmware()
        {
            main.lockInterface(true, true);
            main.addToConsole("---------------------------------------------------");

           

            try
            {
                
                main.addToConsole("search bootloader...");
                Device d = null;
                try
                {
                    d = Device.searchBootLoader();
                }
                catch (Exception)
                {
                    d = Device.searchDevice();
                    try { d.Control.reset(); }
                    catch (Exception) { }
                    d.close();
                    d = null;
                }
                if (d == null) d = Device.searchBootLoader();
                main.addToConsole("OK: bootloader detected");
                main.addToConsole("bootloader version: " + d.Profile.FirmwareVersion);
                int app_end = d.Control.bootAppEnd();
                int page_size = d.Control.bootPageSize();
                main.addToConsole("app end: " + app_end);
                main.addToConsole("page size: " + page_size);
                main.addToConsole("read firmware...");
                
                d.Control.setAddr(0);
                byte[] buff = new byte[app_end / page_size * page_size + page_size];

                for (int i = 0; i < buff.Length / page_size; i++)
                {
                    d.Control.bootReadPage(buff, i * page_size, page_size);
                }
                d.close();
                main.addToConsole("read is done");
                main.addToConsole("save...");
                HexFile hex = HexFile.makeFromBunary(buff, 0, buff.Length);
                String filename = main.saveFileDialog_hex.FileName;
               // if (!filename.Contains(".hex")) filename += ".hex";
                FileStream file = File.Create(filename);
                file.Write(hex.toHex(), 0, hex.toHex().Length);
                file.Close();
                main.addToConsole("done");
            }
            catch (Exception x)
            {
                main.addToConsole("ERROR: " + x.Message);
            }

            main.lockInterface(false);
        }



        public  void checkCRC(Device device, byte [] data, int offset, int len)
        {
            main.addToConsole("verification...");
            UInt16 calc_crc = Crc16.calc(data, offset, len);
            main.addToConsole("ROM crc: " + String.Format("{0:X2}", calc_crc));
            main.addToConsole("calc crc on device...");
            UInt16 recive_crc = device.Control.calcCrcForArea(0, len);
            if (calc_crc != recive_crc)
            {
                throw new Exception("verification failed: device crc = " + String.Format("{0:X2}", recive_crc));
            }
            main.addToConsole("OK: verification done");
        }


    }
}
