// 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.IO;
using System.Reflection;
using Hiperscan.Unix;

namespace Hiperscan.Common
{
	public static class AutoCompletion
	{
		private const string PROGRAM_NAME_PLACE_HOLDER 			= "PROGRAM_NAME";
		private const string ALL_ARGS_PLACE_HOLDER				= "ALL_ARGS";
		private const string PRE_DEFINED_VALUES_PLACE_HOLDER	= "PRE_DEFINED_VALUES";

        public static void CreateAutoCompletionFile(Parser parser, string path)
		{
            Console.WriteLine("Creating auto completion file...");

            if (Directory.Exists(path) == false)
                Directory.CreateDirectory(path);

			Stream s = Assembly.GetExecutingAssembly().GetManifestResourceStream("auto_completion_template.txt");
			using (StreamReader sr = new StreamReader(s, System.Text.Encoding.ASCII))
			{
				string content = sr.ReadToEnd();

                List<IOption> items = parser.OptionSection.Parameters;

                string option_flags = AutoCompletion.GetArgs(items);
                string predefined_values = AutoCompletion.GetPredefinedValues(items);

                content = content.Replace(AutoCompletion.PROGRAM_NAME_PLACE_HOLDER, Parser.ProgramName);
                content = content.Replace(AutoCompletion.ALL_ARGS_PLACE_HOLDER, option_flags);
                content = content.Replace(AutoCompletion.PRE_DEFINED_VALUES_PLACE_HOLDER, predefined_values);

                string file = Path.Combine(path, Parser.ProgramName);
				using (StreamWriter sw = new StreamWriter(file, false, System.Text.Encoding.ASCII))
				{
					sw.Write(content);
				}

				Console.WriteLine("Done.");
			}
		}

        private static string GetArgs(List<IOption> items)
		{
			List<string> args = new List<string>();

            foreach(IOption item in items)
            {
                if (item.Undocumented == true)
                    continue;
                
                if (String.IsNullOrEmpty(item.LongName) == false)
                    args.Add(item.LongName);

                if (String.IsNullOrEmpty(item.ShortName) == false)
                    args.Add(item.ShortName);
			}

			return String.Join(" ", args.ToArray());
		}

        private static string GetPredefinedValues(List<IOption> items)
		{
			string predefined_values = String.Empty;

            foreach (IOption item in items)
			{
                if (item.PredefinedValues.Count == 0 || item.Undocumented == true)
				    continue;

                bool long_option_exists = String.IsNullOrEmpty(item.LongName) == false;

				if ( long_option_exists == true)
                    predefined_values += String.Format( "    if [[  \"$prev\" == \"{0}\" ]]", item.LongName);

                if (String.IsNullOrEmpty(item.ShortName) == true)
				{
					predefined_values += " ; then\n";
				}
				else
				{
					if ( long_option_exists == false)
                        predefined_values += String.Format( "    if [[  \"$prev\" == \"{0}\" ]] ; then\n", item.ShortName);
						else
                        predefined_values += String.Format( " || [[  \"$prev\" == \"{0}\" ]] ; then\n", item.ShortName);
                }

                predefined_values += String.Format("        COMPREPLY=( $( compgen -W \"{0}\" -- \"$cur\" ) )\n",
                                                   String.Join(" ", item.PredefinedValues.ToArray()));
                predefined_values += "        return 0\n";
                predefined_values += "    fi\n\n";
					
			}

			return predefined_values;
		}
	}
}
