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

namespace Rokojori
{  
  public enum FilePathType
  {
    Absolute,
    Relative
  }

  public class FilePath
  {
    public FilePathType type;
    public FilePath parent;
    public string path;

    public string _fileName;
    public string _fileExtension;
    string _fullPath = null;

    /**<summary for="method get_fileName">Only fileName without fileExtension </summary>*/
    public string fileName
    {
      get 
      {
        if ( _fileName == null)
        { 
          _fileName = Path.GetFileNameWithoutExtension( path );
        }

        return _fileName;
      }
    }
    
    /**<summary for="method get_fullFileName">Combines fileName + fileExtension </summary>*/
    public string fullFileName => fileName + fileExtension;

    /**<summary for="method get_fileExtension>File extension including the dot, eg. ".svg", ".jpg", ".js"</summary>*/
    public string fileExtension
    {
      get 
      {
        if ( _fileExtension == null)
        { 
          _fileExtension = Path.GetExtension( path );
        }

        return _fileExtension;
      }
    }

    public bool HasFileExtension( string extension, bool forceDot = true )
    {
      if ( fileExtension == null )
      {
        return false;
      }

      if ( forceDot && ! extension.StartsWith( "." ))
      {
        extension = "." + extension;
      }

      return fileExtension.ToLower() == extension.ToLower();
    }

    public string fullPath
    {
      get
      {
        if ( _fullPath == null )
        {
          if ( this.parent != null )
          {
            _fullPath = this.parent.fullPath + "/" + path;
          }
          else
          {
            _fullPath = path;
          }
          
        }

        return _fullPath;
      }
    }

    public static FilePath Create( string path, FilePathType type = FilePathType.Relative, FilePath parent = null  )
    {
      var rp = new FilePath();

      rp.type = type;
      rp.parent = parent;
      rp.path = path;

      return rp;
    } 

    public FilePath WithExtension( string extension, bool forceDot = true )
    {
      var rp = new FilePath();

      rp.type = type;
      rp.parent = parent;

      if ( forceDot && ! extension.StartsWith( "." ) )
      {
        extension = "." + extension;
      }

      rp.path = Path.ChangeExtension( path, extension );

      return rp;
    }

    public string absoluteParentPath
    {
      get 
      {
        return RegexUtility.ParentPath( fullPath );
      }
    }

    public FilePath ChangeFileName( string fileName )
    {
      var parentPath = absoluteParentPath;     

      if ( ! parentPath.EndsWith( "/" ) )
      {
        parentPath += "/";
      }

      return Absolute( parentPath + fileName + fileExtension );
    }

    public FilePath AddToFileName( string fileNameAddition )
    {
      return ChangeFileName( fileName + fileNameAddition );
    }

    public static FilePath Absolute( string path  )
    {
      return FilePath.Create( path, FilePathType.Absolute );
    }

    public FilePath CreateAbsoluteParent()
    {
      var path = this.fullPath;

      return Absolute( RegexUtility.ParentPath( path ) );
    } 
  

    public FilePath MakeRelative( string path )
    {
      return FilePath.Create( path, FilePathType.Relative, this );
    }

    public FilePath MakeAbsolutePathRelative( string absolutePath )
    {
      absolutePath = FilePath.Normalize( absolutePath );
      var ownAbsolutePath = FilePath.Normalize( fullPath );

      if ( ! absolutePath.StartsWith( ownAbsolutePath ) )
      {
        return null;
      }

      var relativePath = absolutePath.Substring( ownAbsolutePath.Length );
      
      return MakeRelative( relativePath );
    }

    public FilePath CreateRelativeFromAbsolutePathWithParent( string absolutePath, FilePath absoluteParent )
    {
      var rp = new FilePath();
      
      rp.type = FilePathType.Relative;
      rp.parent = absoluteParent;
      rp.path = Path.GetFileName( absolutePath );
      rp._fullPath = absolutePath;

      return rp;

    }

    public static string Normalize( string path, bool removeFirst = true, bool removeLast = true )
    {
      path = Regex.Replace( path, @"\\", "/" );
      path = Regex.Replace( path, @"/+", "/" );

      if ( removeFirst )
      {
        path = Regex.Replace( path, @"^/", "" );
      }
      
      if ( removeLast )
      {
        path = Regex.Replace( path, @"/$", "" );
      }

      

      return path;
    }

    public static string Join( params string[] paths )
    {
      var sb = new StringBuilder();

      for ( int i = 0; i < paths.Length; i++ )
      {
        var path = paths[ i ];

        path = Normalize( path );

        if ( i != 0 )
        {
          sb.Append( "/" );
        }

        sb.Append( path );
      }

      return sb.ToString();
    }

  }
}