using System;
using System.Collections.Generic;
using System.Linq;
using Mono.Options;
using Newtonsoft.Json;

namespace nuget_cli
{
    partial class Program
    {
        private static bool shouldShowHelp;
        private static bool shouldShowSourceHelp;
        private static bool shouldShowPushHelp;
        private static string apiKey = null;
        private static string source = null;
        private static int pushKO = 0;

        static Program()
        {
        }

        static int Main(string[] args)
        {

            var options = new OptionSet {
                { "h|help", "show this message and exit", h => shouldShowHelp = h != null },
            };
            var pushoptions = new OptionSet {
                { "k|api-key=", "use api key", val => apiKey = apiKey ?? val },
                { "s|source=", "use source", val => source = source ?? val },
                { "h|help", "show this message and exit", h => shouldShowPushHelp = h != null },
            };
            var sourceoptions = new OptionSet {
                { "h|help", "show this message and exit", h => shouldShowSourceHelp = h != null },
            };

            var commandSet = new CommandSet("yaget-cli");


            var srclst = new Command("list")
            {
                Run = sargs => SourceList(sargs)
            };
            var srcadd = new Command("add")
            {
                Run = sargs => SourceAdd(sargs)
            };
            var srcCmd = new Command("source")
            {
                Run = sargs => 
                {
                    var pargs = sourceoptions.Parse(sargs);
                    if (shouldShowSourceHelp)
                    {
                        // output the options
                        Console.WriteLine("Push Options:");
                        sourceoptions.WriteOptionDescriptions(Console.Out);
                        return;
                    }
                }
            };

            var sourceCmdSet = new CommandSet("source")
            {
                srclst,
                srcadd
            };

            var add = new Command("add")
            {
                Run = sargs => Add(sargs)
            };
            commandSet.Add(add);

            var push = new Command("push")
            {

                Run = async sargs =>
                {
                    var pargs = pushoptions.Parse(sargs);
                    if (shouldShowPushHelp)
                    {
                        // output the options
                        Console.Error.WriteLine("Push Options:");
                        pushoptions.WriteOptionDescriptions(Console.Out);
                        return;
                    }
                    List<PushReport> reports = await PushPkgAsync(pargs);
                    Console.WriteLine(JsonConvert.SerializeObject(reports));
                    pushKO = reports.Count( r => !r.OK && !r.AlreadyPresent);
                }
            };
            commandSet.Add(push);
            var setapikey = new Command("set-api-key")
            {
                Run = sargs => StoreApiKey(sargs)
            };
            commandSet.Add(setapikey);


            List<string> extra;
            try
            {
                // parse the command line
                extra = options.Parse(args);
            }
            catch (OptionException e)
            {
                // output some error message
                Console.Write("isn: ");
                Console.WriteLine(e.Message);
                Console.WriteLine("Try `isn --help' for more information.");
                return 2;
            }


            if (shouldShowHelp)
            {
                // output the options
                Console.WriteLine("Options:");
                options.WriteOptionDescriptions(Console.Out);
                return 1;
            }
            
            int runCode = commandSet.Run(args);
            if (runCode == 0 ) if (pushKO>0) return 3;

            return runCode;
             
        }
    }
}
