using System;
using System.IO;
using System.Collections.Generic;

using CommonHelpers;

namespace SqlCatPP {

//**************************************************************************************************
static partial class Program {
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

/// <exception cref="ArgumentNullException" />
/// <exception cref="OperationFailedException" />
static void ProcessSingleSource(string filePath)
{
   string fileName = null;
   try { fileName = Path.GetFileName( filePath ); }
   catch {
      throw OpFailedExceptionCreator.Create(
         "Can not obtain file name part of path: \"{0}\".",
         filePath ); }
   if ( Path.GetFileName( filePath ).StartsWith(";") )
      throw OpFailedExceptionCreator.Create(
         "Forbidden explicit specification of \";\"-prefixed (semicolon) file: \"{0}\".",
         filePath );
   FileNameHlp.VerifyFileExists( filePath );
   PrintInputItem( filePath );
   _Scripter_.ProcessSourceFile( filePath );
}

/// <exception cref="ArgumentNullException" />
/// <exception cref="OperationFailedException" />
static void ProcessSourceFiles(string filePattern)
{
   HArgChecking.VerifyNotNull( filePattern );
   if ( !HPath.ContainsWildcardChar( filePattern ) )
   {
      ProcessSingleSource( filePattern );
      return;
   }
   string subfolderPath, fileNamePattern;
   try
   {
      subfolderPath = Path.GetDirectoryName( filePattern );
      fileNamePattern = Path.GetFileName( filePattern );
   }
   catch (Exception e)
   {
      throw OpFailedExceptionCreator.Create(
         "Can not obtain directory/file parts of \"{0}\".\n"+
         "{1}", filePattern, e.Message );
   }
   if ( fileNamePattern == "" )
      throw OpFailedExceptionCreator.Create(
         "File path does not contain file name part: \"{0}\".",
         filePattern );
   if ( HPath.ContainsWildcardChar( subfolderPath ) )
      throw OpFailedExceptionCreator.Create(
         "Wildcard characters in directory part of file path: \"{0}\".",
         filePattern );
   ProcessSourceFolder( HString.EmptyAsNull( subfolderPath ), fileNamePattern );
}

//==================================================================================================

/// <exception cref="ArgumentNullException" />
/// <exception cref="OperationFailedException" />
static void ProcessSourceFolders(string subfolderPattern)
{
   HArgChecking.VerifyNotNull( subfolderPattern );
   if ( !HPath.ContainsWildcardChar( subfolderPattern ) )
   {
      ProcessSourceFolder( subfolderPattern );
      return;
   }
   DirectoryInfo[] directoryInfoArray;
   try
   {
      directoryInfoArray = new DirectoryInfo(
         Directory.GetCurrentDirectory() ).GetDirectories( subfolderPattern );
   }
   catch (Exception e)
   {
      throw OpFailedExceptionCreator.Create(
         "Directory enumeration has failed for pattern \"{0}\".\n"+
         "{1}", subfolderPattern, e.Message );
   }
   foreach (var dirInfo in directoryInfoArray)
      ProcessSourceFolder( dirInfo.Name );
}

/// <exception cref="ArgumentNullException" />
/// <exception cref="ArgumentException" />
/// <exception cref="OperationFailedException" />
static void ProcessSourceFolder( string subfolderPath = null,
                                 string fileNamePattern = null )
{
   if ( subfolderPath == "" )
      throw new ArgumentException(
         "Subfolder path parameter must not be empty.",
         nameof( subfolderPath ) );
   if ( fileNamePattern == "" )
      throw new ArgumentException(
         "File name pattern parameter must not be empty.",
         nameof( fileNamePattern ) );

   string subfolderPath_0 = subfolderPath;

   bool wasSubfolderSpecified = subfolderPath != null;
   if ( !wasSubfolderSpecified )
      subfolderPath = Directory.GetCurrentDirectory();
   HOps.ReplaceNull( ref fileNamePattern, "*.sql" );

   if ( HPath.ContainsWildcardChar( subfolderPath ) )
      throw OpFailedExceptionCreator.Create(
         "Wildcard characters in directory path: \"{0}\".",
         subfolderPath );

   FileNameHlp.VerifyFolderExists( subfolderPath );

   FileInfo[] fileInfoArray;
   try
   {
      fileInfoArray = new DirectoryInfo( subfolderPath ).GetFiles( fileNamePattern );
   }
   catch (Exception e)
   {
      throw OpFailedExceptionCreator.Create(
         "File enumeration of \"{0}\" has failed for subfolder \"{1}\".\n"+
         "{2}", fileNamePattern, subfolderPath, e.Message );
   }
   var fileNames = new List<string>();
   foreach (var fileInfo in fileInfoArray)
      if ( !fileInfo.Name.StartsWith(";") )
         fileNames.Add( fileInfo.Name );
   fileNames.Sort( CaseInsensitiveComparerStr.Instance );
   var orderedFileNames = new OrderList( subfolderPath_0 ).PrepareFileOrder( fileNames );
   if ( subfolderPath_0 != null )
      PrintInputItem( subfolderPath_0, orderedFileNames );
   foreach (var fileName in orderedFileNames)
   {
      string filePath = wasSubfolderSpecified ?
         Path.Combine( subfolderPath, fileName ) :
         fileName;
      if ( subfolderPath_0 == null )
         PrintInputItem( filePath );
      _Scripter_.ProcessSourceFile( filePath );
   }
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
} // Program
//**************************************************************************************************

} // SqlCatPP
