// 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.Text;

namespace Hiperscan.Common.CommandLineArgsParser
{
    public static class IndentTextWriter
    {
        public static void Write(int start_xposition, string text)
        {
            if (Console.CursorLeft > start_xposition)
                Console.WriteLine();
            IndentTextWriter.AdvanceCursor(start_xposition);

            string[] lines = text.Split('\n');
            foreach (string line in lines)
            {
                if (string.IsNullOrEmpty(line))
                {
                    IndentTextWriter.NewLine(start_xposition);
                    continue;
                }

                string[] words = line.Split();
                IndentTextWriter.AddWord(start_xposition, words[0]); // must exist after preceeding 'if'
                for (int i = 1; i < words.Length; ++i)
                {
                    IndentTextWriter.AddSpace(start_xposition, words[i].Length);
                    IndentTextWriter.AddWord(start_xposition, words[i]);
                }
            }
        }

        private static void AddWord(int start_xposition, string word)
        {
            if (string.IsNullOrEmpty(word))
                return;

            if (IndentTextWriter.AvailableLength < word.Length)
                IndentTextWriter.NewLine(start_xposition);

            Console.Write(word);
        }

        private static void AddSpace(int start_xposition, int next_word_length = 0)
        {
            if (Console.CursorLeft + CliEnvironment.WORD_SEPARATOR.Length + next_word_length
                > IndentTextWriter.MaxXPosition)
            {
                IndentTextWriter.NewLine(start_xposition);
            }
            else
            {
                Console.Write(CliEnvironment.WORD_SEPARATOR);
            }
        }

        /// <summary>Moves the cursor in whole <see cref="CliEnvironment.WORD_SEPARATOR"/>s as close as possible to <paramref name="start_xposition"/> without overshooting.</summary>
        /// <example><para>let <see cref="CliEnvironment.WORD_SEPARATOR"/> be "; "</para>
        ///          <para>let <see cref="Console.CursorLeft"/> be <b>0</b></para>
        ///          <code>AdvanceCursor(3)</code>
        ///          will result in <see cref="Console.CursorLeft"/> to be set to 2.</example>
        /// <example><para>let <see cref="CliEnvironment.WORD_SEPARATOR"/> be "; "</para>
        ///          <para>let <see cref="Console.CursorLeft"/> be <b>1</b></para>
        ///          <code>AdvanceCursor(3)</code>
        ///          will result in <see cref="Console.CursorLeft"/> to be set to 3.</example>
        /// <param name="start_xposition">Must be GEQ <see cref="Console.CursorLeft"/>.</param>
        private static void AdvanceCursor(int start_xposition)
        {
            var offset = start_xposition - Console.CursorLeft;
            var separators = offset / CliEnvironment.WORD_SEPARATOR.Length;
            Console.Write(new StringBuilder(offset).Insert(0, CliEnvironment.WORD_SEPARATOR, separators));
        }

        private static void NewLine(int start_xposition)
        {
            /* Console.SetCursorPosition(start_xposition, Console.CursorTop + 1);
             * does not scroll console window but throws at last line.
             * Note: Should - eventually - work according to
             * https://learn.microsoft.com/en-us/dotnet/api/system.console.setcursorposition?view=net-7.0#remarks
             *       so perhaps try again after .NET update.
             */
            Console.WriteLine();
            IndentTextWriter.AdvanceCursor(start_xposition);
        }

        private static int AvailableLength => 1 + IndentTextWriter.MaxXPosition - Console.CursorLeft;

        private static int MaxXPosition => Console.WindowWidth - 1;

        /// <summary>Distance between columns. Rows begin with an Indent.</summary>
        public static int Indent { get; set; } = 2;
    }
}
