using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Microsoft.Win32.SafeHandles;
using System.Runtime.InteropServices;
using System.IO;

namespace Raw_data_00
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            StatusLabel1.Text = "";
        }

        public enum EMoveMethod : uint
        {
            Begin = 0,
            Current = 1,
            End = 2
        }

        [DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        static extern uint SetFilePointer(
            [In] SafeFileHandle hFile,
            [In] uint lDistanceToMove,
            [Out] out int lpDistanceToMoveHigh,
            [In] EMoveMethod dwMoveMethod);

        [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
        static extern SafeFileHandle CreateFile(string lpFileName, uint dwDesiredAccess,
          uint dwShareMode, IntPtr lpSecurityAttributes, uint dwCreationDisposition,
          uint dwFlagsAndAttributes, IntPtr hTemplateFile);

        [DllImport("kernel32", SetLastError = true)]
        internal extern static int ReadFile(SafeFileHandle handle, byte[] bytes,
           int numBytesToRead, out int numBytesRead, IntPtr overlapped_MustBeZero);

        private void trackBarOffset_Scroll(object sender, EventArgs e)
        {
            string barFrom = "Stahovat od " + trackBarOffset.Value + ". hodiny";
            StatusLabel1.Text = barFrom;
        }

        private void trackBarHour_Scroll(object sender, EventArgs e)
        {            
            string bar = "Stáhnovat po " + trackBarHour.Value + ". hodinu včetně";            
            StatusLabel1.Text = bar;
        }

        

        private void buttonDump_Click(object sender, EventArgs e)
        {            
            //short FILE_ATTRIBUTE_NORMAL = 0x80;
            //short INVALID_HANDLE_VALUE = -1;
            uint GENERIC_READ = 0x80000000;
            //uint GENERIC_WRITE = 0x40000000;
            //uint CREATE_NEW = 1;
            //uint CREATE_ALWAYS = 2;
            uint OPEN_EXISTING = 3;
            int checkCard = 1;


            SaveFileDialog mySFD = new SaveFileDialog();
            mySFD.FileName = "Info.txt";
            string address = @"\\.\" + textBoxPath.Text + ":";
            mySFD.InitialDirectory = Path.GetDirectoryName(Application.StartupPath);
            
                SafeFileHandle handleValue = CreateFile(address, GENERIC_READ, 0, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero);
                if (handleValue.IsInvalid)
                {
                    Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
                }

                byte[] buf = new byte[512];                
                int read = 0;
                int moveToHigh;
                SetFilePointer(handleValue, 0, out moveToHigh, EMoveMethod.Begin);
                ReadFile(handleValue, buf, 512, out read, IntPtr.Zero); 

                StreamWriter blockZero = new StreamWriter(mySFD.FileName, false, Encoding.GetEncoding(1250));
                uint log = buf[0];
                int logS = buf[0];
                if (log == 255) log = 60;
                uint per = buf[1];
                int perS = buf[1];
                if (per == 255) per = 60;
                int hour = buf[2];
                blockZero.WriteLine("Délka jednotlivých záznamů: {0} min.", log);
                blockZero.WriteLine("Délka periody: {0} min.", per);
                blockZero.WriteLine("Nastavená délka nahrávání: {0} hod.", hour);

                blockZero.Close();
                handleValue.Close();
                
                if (hour > 48 && (log != 1 || log != 5 || log != 10 || log != 15
                    || log != 60) && (per != 5 || per != 20 || per != 30 || per != 60))
                {
                    checkCard = 0;
                }
                int setHour = trackBarHour.Value;
                if (setHour > hour)
                {
                    setHour = hour;
                }

                int setOffset = trackBarOffset.Value - 1;
                if (setOffset >= hour)
                {
                    setOffset = hour - 1;
                }

                uint sector = 140526;
                uint[] block = new uint[setHour + 1];
                block[0] = 1;
                
                for (int i = 1; i < (setHour + 1); i++)
                {
                    block[i] = ((sector / per) * log) + block[i - 1] ;                                        
                }

                int sectorS = 140526;
                int[] blockS = new int[setHour + 1];
                blockS[0] = 1;

                for (int i = 1; i < (setHour + 1); i++)
                {
                    blockS[i] = ((sectorS / perS) * logS) + blockS[i - 1];
                }

                
                                
                int size;
                uint offset;                
                if (checkCard == 1)
                {
                    for (int i = setOffset; i < setHour; i++)
                    {
                        mySFD.FileName = "Data_Hodina_" + (i + 1) + ".txt";
                        offset = block[i] * 512;
                        size = (blockS[i + 1] - blockS[i]) * 512;                        
                        byte[] buffer = new byte[size];

                        SafeFileHandle fileHandle = CreateFile(address, GENERIC_READ, 0, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero);
                        if (handleValue.IsInvalid)
                        {
                            Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
                        }
                        //SafeFileHandle fileHandle = CreateFile(address, 0x80000000, 0, IntPtr.Zero, 3, 0, IntPtr.Zero);
                        //FileStream readStream = new FileStream(fileHandle, FileAccess.Read); //The stream to be read. Is converted to binary.
                        //BufferedStream bufStream = new BufferedStream(readStream, size);
                        StreamWriter blockData = new StreamWriter(mySFD.FileName, false, Encoding.GetEncoding(1250));

                        int bytesRead;

                        try
                        {
                            int readB = 0;
                            int moveHigh;
                            SetFilePointer(fileHandle, offset, out moveHigh, EMoveMethod.Begin);
                            ReadFile(fileHandle, buffer, size, out readB, IntPtr.Zero); //Read from SD card to buffer
                            int ppg1, ppg2, bp, ecg;
                            for (int j = 0; j < size; j = (j + 4))
                            {
                                if (buffer[j] == 255)
                                {
                                    ppg1 = buffer[j] * 100;
                                    ppg2 = buffer[j + 1];
                                    bp = buffer[j + 2];
                                    ecg = buffer[j + 3];
                                }
                                else
                                {
                                    ppg1 = (buffer[j] * 3300) / 255;
                                    ppg2 = (buffer[j + 1] * 3300) / 255;
                                    bp = (buffer[j + 2] * 3300) / 255;
                                    ecg = (buffer[j + 3] * 3300) / 255;
                                }                            
                               
                                blockData.WriteLine("{0},{1},{2},{3},", ppg1, ppg2, bp, ecg);
                                StatusLabel1.Text = "Stahování dokončeno";
                            }

                        }

                        catch (System.IO.FileNotFoundException ex)
                        {
                            StatusLabel1.Text = "Chyba stahování";
                            blockData.Close();
                            handleValue.Close();
                            //bufStream.Close();
                            fileHandle.Close(); //Close the SD card file.
                            //readStream.Close(); //Close the filestream reader.
                            System.Environment.Exit(1);
                        }

                        catch (System.ArgumentException ex)
                        {
                            StatusLabel1.Text = "Chyba stahování";
                            blockData.Close();
                            handleValue.Close();
                            fileHandle.Close(); //Close the SD card file.
                            //readStream.Close(); //Close the filestream reader.                        
                            System.Environment.Exit(1);
                        }

                        fileHandle.Close(); //Close the SD card file.
                        //readStream.Close(); //Close the filestream reader.
                        //bufStream.Close();
                        blockData.Close();
                        //handleValue.Close();
                    }                    
                }
                else if (checkCard == 0)
                {
                    StatusLabel1.Text = "Chybná SD karta";
                }
                
                
        }

       

        

        
    }
}
