using CommandLine;
using CommandLine.Text;
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;

namespace mx_pcie_ctl
{
    class Program
    {
        class Options
        {
            [Option('i', Required = true, HelpText = "-i <#PCIE Slot index> (Start from 0)")]
            public uint PCIESlotIndex { get; set; }

            [Option('m', Default = null,
                HelpText = "-m <pcie power status>\n" +
                " 		0 --> PCIE power off\n" +
                "		1 --> PCIE power on\n"
                )]
            public int? PCIEStatus { get; set; }

            [Option('t', Default = null, HelpText = "-t <#PCIE Reset Delay time(ms)>")]
            public int? DelayTime { get; set; }

            [Usage(ApplicationAlias = "mx-pcie-ctl")]
            public static IEnumerable<Example> Examples
            {
                get
                {
                    yield return new Example("Get pcie power status from pcie slot 1", new Options { PCIESlotIndex = 1 });
                    yield return new Example("Set pcie slot 1 power on", new Options { PCIESlotIndex = 1, PCIEStatus = 1 });
                    yield return new Example("Set pcie slot 1 power on with delay Time 200ms", new Options { PCIESlotIndex = 1, PCIEStatus = 1, DelayTime=200 });
                }
            }
        }

        [DllImport("mxpcie.dll", EntryPoint = "GetPCIESlotStatus", CharSet = CharSet.Ansi, SetLastError = true)]
        public static extern int GetPCIESlotStatus(int port);

        [DllImport("mxpcie.dll", EntryPoint = "SetPCIESlotStatusWithReset", CharSet = CharSet.Ansi, SetLastError = true)]
        public static extern int SetPCIESlotStatusWithReset(int port, int mode,int time);

        [DllImport("mxpcie.dll", EntryPoint = "SetPCIESlotStatus", CharSet = CharSet.Ansi, SetLastError = true)]
        public static extern int SetPCIESlotStatus(int port, int mode);

        public struct Action_Struct
        {
            public int index;
            public int number;
            public int time;
        };

        static void Main(string[] args)
        {
            CommandLine.Parser.Default.ParseArguments<Options>(args)
                .WithParsed(opts =>
                {
                    if (opts.PCIEStatus == null)
                    {
                        GetModeAction(opts);
                    }
                    else
                    {
                        SetModeAction(opts);
                    }
                });
        }

        private static void SetModeAction(Options opts)
        {
            Action_Struct action;
            action.index = (int)opts.PCIESlotIndex;    
           
            if (opts.DelayTime !=null)
            {
               
                if (SetPCIESlotStatusWithReset(action.index, (int)opts.PCIEStatus, (int)opts.DelayTime) < 0)
                {
                    Console.WriteLine("Failed to set PCIE slot {0} power status.", action.index);
                }
                else
                {
                    action.number = GetPCIESlotStatus(action.index);
                    if (action.number >= 0)
                    {
                        Console.WriteLine("PCIE slot {0} power status: {1}", action.index, action.number);
                    }
                }
            }
            else
            {
                if (SetPCIESlotStatus(action.index, (int)opts.PCIEStatus) < 0)
                {
                    Console.WriteLine("Failed to set PCIE slot {0} power status.", action.index);
                }
                else
                {
                    action.number = GetPCIESlotStatus(action.index);
                    if (action.number >= 0)
                    {
                        Console.WriteLine("PCIE slot {0} power status: {1}", action.index, action.number);
                    }
                }

            }
            
        }

        private static void GetModeAction(Options opts)
        {
            Action_Struct action;
            action.index = (int)opts.PCIESlotIndex;
            action.number = GetPCIESlotStatus(action.index);
            if (action.number >= 0)
            {
                Console.WriteLine(string.Format("PCIE slot {0} power status: {1}", action.index, action.number));
            }
        }
    }
}
