// Created with MonoDevelop
//
//    Copyright (C) 2018 Hiperscan GmbH Dresden, Germany
//
//    This program is free software: you can redistribute it and/or modify
//    it under the terms of the GNU General Public License as published by
//    the Free Software Foundation, either version 3 of the License, or
//    (at your option) any later version.
//
//    This program is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//    GNU General Public License for more details.
//
//    You should have received a copy of the GNU General Public License
//    along with this program.  If not, see <http://www.gnu.org/licenses/>.

using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Text.RegularExpressions;

using Hiperscan.Unix;

namespace Hiperscan.Common.CommandLineArgsParser
{
    public static class StandardParser
    {
        public static object StringParser(List<string> values, Type type, int number_of_calls)
        {
            string value = values[values.Count - 1];
            return value;
        }

        public static object BooleanParser(List<string> values, Type type, int number_of_calls)
        {
            string value = values[values.Count - 1];
            return bool.Parse(value);
        }

        public static object Int32Parser(List<string> values, Type type, int number_of_calls)
        {
            string value = values[values.Count - 1];
            return Int32.Parse(value, CultureInfo.InvariantCulture);
        }

        public static object UInt32HexParser(List<string> values, Type type, int number_of_calls)
        {
            string value = values[values.Count - 1];
            return UInt32.Parse(value, System.Globalization.NumberStyles.HexNumber);
        }

        public static object UInt32arser(List<string> values, Type type, int number_of_calls)
        {
            string value = values[values.Count - 1];
            return UInt32.Parse(value);
        }

        public static object Int32GreaterThanZeroParser(List<string> values, Type type, int number_of_calls)
        {
            int value = (int)StandardParser.Int32Parser(values, type, number_of_calls);
            if (value < 1)
                throw new ArgumentException(Catalog.GetString("Value must be greater than zero"));
            return value;
        }

        public static object UInt16Parser(List<string> values, Type type, int number_of_calls)
        {
            string value = values[values.Count - 1];
            return UInt16.Parse(value);
        }

        public static object UShortParser(List<string> values, Type type, int number_of_calls)
        {
            string value = values[values.Count - 1];
            return ushort.Parse(value);
        }

        public static object DoubleParser(List<string> values, Type type, int number_of_calls)
        {
            string value = values[values.Count - 1];
            return double.Parse(value, CultureInfo.InvariantCulture);
        }

        public static object SingleEnumParser(List<string> values, Type type, int number_of_calls)
        {
            if (number_of_calls > 1)
                throw new Exception(Catalog.GetString("Option can only be used once."));

            return StandardParser.EnumParser(values, type, number_of_calls);
        }

        public static object EnumParser(List<string> values, Type type, int number_of_calls)
        {
            string value = values[values.Count - 1];
            return Enum.Parse(type, value, true);
        }

        public static object VersionParser(List<string> values, Type type, int number_of_calls)
        {
            return new Version(values[values.Count - 1]);
        }

        public static object DateTimeParser(List<string> values, Type type, int number_of_calls)
        {
            DateTime date;
            try
            {
                date = DateTime.Parse(values[values.Count - 1], CultureInfo.CurrentCulture);
            }
            catch
            {
                date = DateTime.Parse(values[values.Count - 1], CultureInfo.InvariantCulture);
            }
            return date;
        }

        public static object SwitchOn(List<string> values, Type type, int number_of_calls)
        {
            return true;
        }

        public static object SwitchOff(List<string> values, Type type, int number_of_calls)
        {
            return false;
        }

        public static object FileStringParser(List<string> values, Type type, int number_of_calls)
        {
            string file = values[values.Count - 1];
            if (FileIO.ExistsDirectory(file))
                throw new ArgumentException(Catalog.GetString("This file exists already as directory."));

            return Path.GetFullPath(file);
        }

        public static object DirectoryStringParser(List<string> values, Type type, int number_of_calls)
        {
            string dir = values[values.Count - 1];

            if (FileIO.ExistsFile(dir))
                throw new ArgumentException(Catalog.GetString("This path exists already as file."));

            return Path.GetFullPath(dir);
        }

        public static object PortParser(List<string> values, Type type, int number_of_calls)
        {
            string value = values[values.Count - 1];
            int port = Int32.Parse(value, CultureInfo.InvariantCulture);
            if (port < 0 || port > 65535)
                throw new ArgumentException(Catalog.GetString("Port number must be a value between 0 and 65535."));

            return port;
        }

        public static object RegexParser(List<string> values, Type type, int number_of_calls)
        {
            return new Regex(values[values.Count - 1]);
        }

        public static object StringArrayParser(List<string> values, Type type, int number_of_calls)
        {
            return values;
        }
    }
}
