using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Microsoft.Win32;

namespace Stimuli_Creator
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    /// 

    public partial class MainWindow : Window
    {
        //Line myLine;
        double selectedMhz = 0;
        registerStatus stimuliPoints = new registerStatus();
        int pageStart = 0;
        int step;
        double period = 0;
        double stepTime = 0;

        public MainWindow()
        {
            InitializeComponent();
        }

        private void stepSizeUpdater()
        {

            //double selectedMHZ;
            if (registerSelection == null || seconds == null || stepSize == null || errorLabel == null)
                return;

            //errorLabel.Visibility = Visibility.Hidden;
            createBtn.IsEnabled = true;
            double.TryParse((MHz.Text.ToString()), out selectedMhz);
            /* double*/
            period = 1 / (selectedMhz * 1000000);
            /* double*/
            stepTime = 0;
            double.TryParse((stepSize.Text), out stepTime);
            if (seconds.SelectedIndex == 1)
                stepTime = stepTime / 1000;
            else if (seconds.SelectedIndex == 2)
                stepTime = stepTime / 1000000;
            //int step;
            if (stepTime < period && stepTime != 0)
            {
                MessageBox.Show("Stepsize too small");
                //errorLabel.Text = "Step size too small";
                //errorLabel.Visibility = Visibility.Visible;
                //createBtn.IsEnabled = false;
                return;
            }
            if (stepTime < 0)
                createBtn.IsEnabled = true;

            step = (int)(stepTime / period);

            //System.Diagnostics.Debug.WriteLine(stepTime);
            ////System.Diagnostics.Debug.WriteLine(selectedMHZ);
            Double tmp = 0;
            Double.TryParse(stepSize.Text, out tmp);
            stepStart.Text = ((double)(pageStart) * tmp) + " " + seconds.Text;
            stepStop.Text = ((double)(pageStart + 20) * tmp) + " " + seconds.Text;
        }
        private void createBtn_Click(object sender, EventArgs e)
        {
            SaveFileDialog saveDialog = new SaveFileDialog();
            saveDialog.Filter = "Atmel stimuli files | *.stim;*.STIM | All files | *.*";
            saveDialog.DefaultExt = ".stim";
            saveDialog.FileName = registerSelection.Text + "_STIMFILE";

            if (saveDialog.ShowDialog() == true)
            {

                using (System.IO.StreamWriter writer = new System.IO.StreamWriter(saveDialog.FileName))
                {

                    writer.WriteLine("// Atmel Simulator 2 stimuli file created with Stimuli Creator");
                    // writer.Write((registerSelection.Text) + "=");
                    if ((bool)loopSelection.IsChecked)
                    {
                        writer.Write("$repeat ");
                        writer.WriteLine(loopCount.Text);
                    }
                    int _registerValue = 0;
                    int _registerValuePrevious = 0;
                    int _prevTime = 0;
                    for (int _i = 0; _i < stimuliPoints.checkPage(); _i++)
                    {
                        _registerValuePrevious = _registerValue;
                        _registerValue = 0;
                        for (int _j = 0; _j < 8; _j++)
                        {

                            if (stimuliPoints.getbitlist(_j, _i))
                            {
                                _registerValue += (int)Math.Pow(2, _j);
                            }
                        }

                        if (_registerValuePrevious != _registerValue)
                        {
                            if (0 != ((_i * step) - _prevTime))
                                writer.WriteLine("#" + ((_i * step) - _prevTime));
                            writer.WriteLine(registerSelection.Text + " = " + _registerValue);
                            _prevTime = (_i * step);
                        }
                    }
                    if ((bool)loopSelection.IsChecked)
                    {
                        writer.Write("$endrep ");
                    }
                }
                //System.Diagnostics.Debug.WriteLine(saveDialog.FileName);
            }
        }




        private void Canvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            Point _location = Mouse.GetPosition(((Canvas)sender));
            //System.Diagnostics.Debug.WriteLine(_location);
            //System.Diagnostics.Debug.WriteLine((int)(_location.Y / 90));
            int _Yloc = (int)(_location.Y / 90);
            int _Xloc = (int)((_location.X - 10) / 50);

            stimuliPoints.setbitlist(_Yloc, _Xloc + pageStart, !(stimuliPoints.getbitlist(_Yloc, _Xloc + pageStart)));
            lineUpdate(sender, e, _Xloc, _Yloc);
        }

        private void canvasFormat(object sender, RoutedEventArgs e)
        {
            //System.Diagnostics.Debug.WriteLine(sender);
            for (int _j = 0; _j < 20; _j++)
            {
                for (int _i = 0; _i < 8; _i++)
                {
                    Line myLine = new Line();
                    myLine.Stroke = System.Windows.Media.Brushes.Blue;
                    myLine.StrokeThickness = 4;
                    myCanvas0.Children.Add(myLine);
                    lineUpdate(myCanvas0, e, _j, _i);
                }
            }
           
        }
        private void pageChange(object sender, RoutedEventArgs e)
        {

            if (sender.Equals(prevPage))
            {
                //System.Diagnostics.Debug.WriteLine(stimuliPoints.checkPage());
                if (pageStart != 0)
                {
                    pageStart -= 20;
                }
                for (int _j = 0; _j < 8; _j++)
                {
                    for (int _i = 0; _i < 20; _i++)
                    {
                        lineUpdate(myCanvas0, e, _i, _j);
                    }
                }
            }

            else if (sender.Equals(nextPage))
            {
                pageStart += 20;
                if (stimuliPoints.checkPage() > pageStart)
                {
                    for (int _j = 0; _j < 20; _j++)
                    {
                        for (int _i = 0; _i < 8; _i++)
                        {
                            lineUpdate(myCanvas0, e, _j, _i);
                        }
                    }
                }
                else
                {
                    for (int _j = pageStart; _j < pageStart + 20; _j++)
                    {
                        for (int _i = 0; _i < 8; _i++)
                        {
                            stimuliPoints.setbitlist(_i, _j, ((bool)defaultBitState.IsChecked), (bool)defaultBitState.IsChecked);
                        }
                    }
                    for (int _j = 0; _j < 20; _j++)
                    {
                        for (int _i = 0; _i < 8; _i++)
                        {
                            lineUpdate(myCanvas0, e, _j, _i);
                        }
                    }
                }
            }
            Double tmp = 0;
            Double.TryParse(stepSize.Text, out tmp);
            stepStart.Text = ((double)(pageStart) * tmp) + " " + seconds.Text;
            stepStop.Text = ((double)(pageStart + 20) * tmp) + " " + seconds.Text;
        }
        private void lineUpdate(object sender, RoutedEventArgs e, int _time, int _bit)
        {
            Line newLine = new Line();
            newLine = (Line)((Canvas)sender).Children[(8 + (8 * _time) + _bit)];
            newLine.X1 = (((_time) * 50) + 10);
            newLine.X2 = (((_time) * 50) + 60);
            if (!(stimuliPoints.getbitlist(_bit, _time + pageStart)))
            {
                newLine.Y1 = newLine.Y2 = ((_bit * 90) + (80));
            }
            else
            {
                newLine.Y1 = newLine.Y2 = ((_bit * 90) + (20));
            }
        }


        private void stepSize_TextChanged(object sender, TextChangedEventArgs e)
        {
            stepSizeUpdater();
        }

        private void seconds_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            stepSizeUpdater();
        }

        private void MHz_TextChanged(object sender, TextChangedEventArgs e)
        {
            stepSizeUpdater();
        }

        private void registerSelection_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (registerSelection.SelectedIndex != -1)
            {
                createBtn.IsEnabled = true;
            }
        }

        private void defaultBitState_Checked(object sender, RoutedEventArgs e)
        {
            for (int _j = pageStart; _j < pageStart + 20; _j++)
            {
                for (int _i = 0; _i < 8; _i++)
                {
                    stimuliPoints.setbitlist(_i, _j, ((bool)defaultBitState.IsChecked));
                }
            }
            for (int _j = 0; _j < 20; _j++)
            {
                for (int _i = 0; _i < 8; _i++)
                {
                    lineUpdate(myCanvas0, e, _j, _i);
                }
            }
        }

        private void clrBtn_Click(object sender, RoutedEventArgs e)
        {
            pageStart = 0;
            stimuliPoints = null;
            stimuliPoints = new registerStatus(8);
            for (int _j = 0; _j < 20; _j++)
            {
                for (int _i = 0; _i < 8; _i++)
                {
                    lineUpdate(myCanvas0, e, _j, _i);
                }
            }
            Double tmp = 0;
            Double.TryParse(stepSize.Text, out tmp);
            stepStart.Text = ((double)(pageStart) * tmp) + " " + seconds.Text;
            stepStop.Text = ((double)(pageStart + 20) * tmp) + " " + seconds.Text;
        }


    }

    public class registerStatus
    {
        private List<List<bool>> _bitlist = new List<List<bool>>();
        private int _bitCnt = 8;
        public registerStatus()
        {
            for (int _j = 0; _j < 20; _j++)
            {
                List<bool> _rangeList = new List<bool>();
                for (int _i = 0; _i < 8; _i++)
                {
                    _rangeList.Add(false);
                }
                _bitlist.Add(_rangeList);
            }
        }
        public registerStatus(int bitCnt)
        {
            _bitCnt = bitCnt;
            for (int _j = 0; _j < 20; _j++)
            {
                List<bool> _rangeList = new List<bool>();
                for (int _i = 0; _i < _bitCnt; _i++)
                {
                    _rangeList.Add(false);
                }
                _bitlist.Add(_rangeList);
            }
        }
        public void setbitlist(int bit, int timePos, bool value)
        {
            if (_bitlist.Count <= timePos)
            {
                List<bool> _rangeList = new List<bool>();
                for (int _i = 0; _i < 8; _i++)
                {
                    _rangeList.Add(false);
                }
                _bitlist.Add(_rangeList);
                return;
            }
            else
                _bitlist[timePos][bit] = value;
        }

        public void setbitlist(int bit, int timePos, bool value, bool defaultState)
        {
            if (_bitlist.Count <= timePos)
            {
                List<bool> _rangeList = new List<bool>();
                for (int _i = 0; _i < 8; _i++)
                {
                    _rangeList.Add(defaultState);
                }
                _bitlist.Add(_rangeList);
                return;
            }
            else
                _bitlist[timePos][bit] = value;
        }

        public bool getbitlist(int bit, int timePos)
        {
            return _bitlist[timePos][bit];
        }
        public int checkPage()
        {
            return (_bitlist.Count);
        }
    }
}
