import { MemberInitializer } from "../MemberInitializer";
import { MemberType } from "../MemberType";
import { Member } from "./Member";

export class Method extends Member
{
  constructor( memberInitializer:MemberInitializer )
  { 
    super( MemberType.Method, memberInitializer ); 
  }

  implementation:string[] = null;

  get hasMethodImplementation()
  {
    return this.implementation != null;
  }

  getMethodImplementation( className:string )
  {
    let lines = [];

    lines.push( this.info() );
    lines.push( `${this.type} ${className}::${this.name}${this.parameterWithBrackets}`);
    lines.push( "{" );

    this.implementation.forEach( l => lines.push( "  " + l ) );    
    lines.push( "}" );

    return lines.join( "\n" ) + "\n";
  }

  parseBody( body:any )
  {
    if ( Array.isArray( body ) )
    {
      let parameters = body[ 0 ];
      let lines = body[ 1 ];
      
      this.parseMethodParameters( parameters );
      this.implementation = lines;
    } 
    else
    {
      return this.parseMethodParameters( body );
    }
    
  }

  get parameterWithBrackets()
  {
    let parameters = this.parametersDefinition === "" ? "()" :
    `( ${this.parametersDefinition} )`;

    return parameters;
  }

  getHeaderDefinition():string
  {
    let methodInfo = "\n  " + this.info() + "\n  ";

    if ( this.isVirtual )
    {
      let numParameters = this.parameters.length;
      let methodReturnType = this.type === "void" ? "" : "R";
      let returnTypeDefinition = this.type === "void" ? "" : ( this.type + ", " ) ;

      let parametersDefinition = "";

      if ( numParameters > 0 )
      {
        parametersDefinition = ", " + this.parameters.map( p => p.type ).join( ", " );
      }


      return `${methodInfo}GDVIRTUAL${numParameters}${methodReturnType}( ${returnTypeDefinition}${this.name}${parametersDefinition} );`
    }

    let parameters = this.parameterWithBrackets;

    return `${methodInfo}${this.type} ${this.name}${parameters};`
  }

 

  getBindings( className:string )
  {
    if ( this.isVirtual )
    {
      let parameterInfos = "";

      for ( let i = 0; i < this.parameters.length; i++ )
      {
        let name = `, "${this.parameters[ i ].name}"`;
        
        parameterInfos += name;
      }

      return `GDVIRTUAL_BIND( ${this.name}${parameterInfos} );`;
    }
    else
    {
      return `ClassDB::bind_method( D_METHOD( "${this.name}" ) , &${className}::${this.name} );`
    }
  }
}