
using Godot;

using Rokojori;
using System.Collections.Generic;
using System;
using System.Reflection;
using System.Text.RegularExpressions;
using System.Linq;
using Rokojori.Tools;

namespace Rokojori.DocGenerator
{
  public class ClassDocEditor
  { 
    public static readonly bool NO_SIGNATURE_FALLBACK_MODE = true;

    public string source;
    public LexerList originalTokens;
    
    ClassDocParser parser;


    public void Process( CSharpObjectDefinition definition, OnlineDocJSON onlineDocJSON )
    {
      parser = new ClassDocParser();
      parser.orginalTokens = originalTokens;
      parser.orginalTokens.ignore = LexerMatcherLibrary.Ignore;
      
      parser.linesMapper = new TextLinesMapper(); 
      parser.linesMapper.Map( source );
      parser.Parse( definition );

      var members = parser.GetMembers();
    
      members.ForEach(
        ( m )=>
        {
          var name = parser.innerTokens[ m.name ].match;
          var type = parser.innerTokens.Range( m.type ).match;

          var parameters = "";


          var isMethod = m.IsMethod( parser.innerTokens );

          if ( isMethod )
          {
            var types = m.GetMethodParameterTypes( parser.innerTokens );    
            
            parameters = "(" + types.Join( "," ) + ")";
          }
          else
          {
            var next = parser.innerTokens.Get( m.name, LexerMatcherLibrary.Ignore );
            var anchorNext = parser.linesMapper.GetAnchor( next.offset, true );
            var anchorName = parser.linesMapper.GetAnchor( parser.innerTokens[ m.name ].offset, true );

            // RJLog.Log( anchorName.info, anchorNext.info );
          }



          var comment = "/** */";

          if ( m.comment != -1 )
          {
            comment = parser.innerTokens[ m.comment ].match;
          }

          var onlineDocEntries = GetOnlineDoc( members, members.IndexOf( m ), onlineDocJSON );

          // RJLog.Log( "Online docs:", onlineDocEntries == null ? "---" : onlineDocEntries.Count );
          

          if ( onlineDocEntries != null )
          {
            var title = onlineDocEntries[ 0 ].content;
            var description = onlineDocEntries[ 1 ].content;

            comment = 
            @$"
            /** 
              <summary>
                
                <title>
                  {title}
                </title>
                
                <description>
                  {description}
                </description>

              </summary>  
            */

            ".Indent( "" );
          }


          RJLog.Log( "[color=#888888]" + comment + "[/color]", "\n" + type, name + parameters );
        }
      );
      
    }

    List<OnlineDocJSONDocEntry> GetOnlineDoc( List<ClassDocMember> members, int index, OnlineDocJSON onlineDoc )
    {
      if ( NO_SIGNATURE_FALLBACK_MODE )
      {
        return GetOnlineDoc_FALLBACK( members, index, onlineDoc );
      }

      return null;
    }

    List<OnlineDocJSONDocEntry> GetOnlineDoc_FALLBACK( List<ClassDocMember> members, int index, OnlineDocJSON onlineDoc )
    {
      var member = members[ index ];

      var membersWithSameName = members.Filter( m => m.name == member.name );

      var name = parser.innerTokens[ member.name ].match;

      var docNames = onlineDoc.content.Map( e => OnlineDocsTarget.From( e.target ).memberName ).Join( "," );
      var docEntries = onlineDoc.content.Filter( e => OnlineDocsTarget.From( e.target ).memberName == name );

      if ( docEntries == null || docEntries.Count == 0 )
      {
        // RJLog.Log( "No doc entries for:", "'" + name + "'", ">>", docNames ); 
        return null;
      }

      if ( membersWithSameName.Count == 1 )
      {
        return docEntries;
      }

      
      var memberIndex = membersWithSameName.IndexOf( member );

      var docEntryIndex  = memberIndex * 2;

      if ( ( docEntryIndex + 1 ) >= docEntries.Count )
      {
        return null;
      }

      return docEntries.Sub( docEntryIndex, 2 );
      
    }

  }
}