import * as _ from 'lodash';
import * as React from 'react';
import * as ReactDOM from 'react-dom';

import { DocsInfo } from '../docs_info';
import { Parameter, SolidityMethod, TypeDefinitionByName, TypescriptMethod } from '../types';
import { constants } from '../utils/constants';

import { Type } from './type';

export interface MethodSignatureProps {
    method: TypescriptMethod | SolidityMethod;
    sectionName: string;
    shouldHideMethodName?: boolean;
    shouldUseArrowSyntax?: boolean;
    typeDefinitionByName?: TypeDefinitionByName;
    docsInfo: DocsInfo;
}

const defaultProps = {
    shouldHideMethodName: false,
    shouldUseArrowSyntax: false,
};

export const MethodSignature: React.SFC<MethodSignatureProps> = (props: MethodSignatureProps) => {
    const sectionName = constants.TYPES_SECTION_NAME;
    const parameters = renderParameters(props.method, props.docsInfo, sectionName, props.typeDefinitionByName);
    const paramStringArray: any[] = [];
    // HACK: For now we don't put params on newlines if there are less then 2 of them.
    // Ideally we would check the character length of the resulting method signature and
    // if it exceeds the available space, put params on their own lines.
    const hasMoreThenTwoParams = parameters.length > 2;
    _.each(parameters, (param: React.ReactNode, i: number) => {
        const finalParam = hasMoreThenTwoParams ? (
            <span className="pl2" key={`param-${i}`}>
                {param}
            </span>
        ) : (
            param
        );
        paramStringArray.push(finalParam);
        const comma = hasMoreThenTwoParams ? (
            <span key={`param-comma-${i}`}>
                , <br />
            </span>
        ) : (
            ', '
        );
        paramStringArray.push(comma);
    });
    if (!hasMoreThenTwoParams) {
        paramStringArray.pop();
    }
    const methodName = props.shouldHideMethodName ? '' : props.method.name;
    const typeParameterIfExists = _.isUndefined((props.method as TypescriptMethod).typeParameter)
        ? undefined
        : renderTypeParameter(props.method, props.docsInfo, sectionName, props.typeDefinitionByName);
    return (
        <span style={{ fontSize: 15 }}>
            {props.method.callPath}
            {methodName}
            {typeParameterIfExists}({hasMoreThenTwoParams && <br />}
            {paramStringArray})
            {props.method.returnType && (
                <span>
                    {props.shouldUseArrowSyntax ? ' => ' : ': '}{' '}
                    <Type
                        type={props.method.returnType}
                        sectionName={sectionName}
                        typeDefinitionByName={props.typeDefinitionByName}
                        docsInfo={props.docsInfo}
                    />
                </span>
            )}
        </span>
    );
};

MethodSignature.defaultProps = defaultProps;

function renderParameters(
    method: TypescriptMethod | SolidityMethod,
    docsInfo: DocsInfo,
    sectionName: string,
    typeDefinitionByName?: TypeDefinitionByName,
) {
    const parameters = method.parameters;
    const params = _.map(parameters, (p: Parameter) => {
        const isOptional = p.isOptional;
        const type = (
            <Type
                type={p.type}
                sectionName={sectionName}
                typeDefinitionByName={typeDefinitionByName}
                docsInfo={docsInfo}
            />
        );
        return (
            <span key={`param-${p.type}-${p.name}`}>
                {p.name}
                {isOptional && '?'}: {type}
            </span>
        );
    });
    return params;
}

function renderTypeParameter(
    method: TypescriptMethod,
    docsInfo: DocsInfo,
    sectionName: string,
    typeDefinitionByName?: TypeDefinitionByName,
) {
    const typeParameter = method.typeParameter;
    const typeParam = (
        <span>
            {`<${typeParameter.name} extends `}
            <Type
                type={typeParameter.type}
                sectionName={sectionName}
                typeDefinitionByName={typeDefinitionByName}
                docsInfo={docsInfo}
            />
            {`>`}
        </span>
    );
    return typeParam;
}
anches/2018Q3</option>
<option value='branches/2018Q4'>branches/2018Q4</option>
<option value='branches/2019Q1'>branches/2019Q1</option>
<option value='branches/2019Q2'>branches/2019Q2</option>
<option value='branches/2019Q3'>branches/2019Q3</option>
<option value='branches/2019Q4'>branches/2019Q4</option>
<option value='branches/2020Q1'>branches/2020Q1</option>
<option value='branches/2020Q2'>branches/2020Q2</option>
<option value='branches/2020Q3'>branches/2020Q3</option>
<option value='branches/2020Q4'>branches/2020Q4</option>
<option value='branches/2021Q1'>branches/2021Q1</option>
<option value='branches/RELEASE_8_4_0'>branches/RELEASE_8_4_0</option>
<option value='branches/RELENG_2_1_0'>branches/RELENG_2_1_0</option>
<option value='branches/RELENG_2_2'>branches/RELENG_2_2</option>
<option value='branches/RELENG_9_1_0'>branches/RELENG_9_1_0</option>
<option value='branches/RELENG_9_2_0'>branches/RELENG_9_2_0</option>
<option value='dependabot/npm_and_yarn/devel/electron4/files/eslint-utils-1.4.3'>dependabot/npm_and_yarn/devel/electron4/files/eslint-utils-1.4.3</option>
<option value='dependabot/npm_and_yarn/devel/electron4/files/lodash-4.17.15'>dependabot/npm_and_yarn/devel/electron4/files/lodash-4.17.15</option>
<option value='dependabot/npm_and_yarn/devel/electron4/files/lodash.merge-4.6.2'>dependabot/npm_and_yarn/devel/electron4/files/lodash.merge-4.6.2</option>
<option value='dependabot/npm_and_yarn/devel/electron4/files/lodash.template-4.5.0'>dependabot/npm_and_yarn/devel/electron4/files/lodash.template-4.5.0</option>
<option value='dependabot/npm_and_yarn/devel/electron4/files/minimist-1.2.2'>dependabot/npm_and_yarn/devel/electron4/files/minimist-1.2.2</option>
<option value='dependabot/npm_and_yarn/devel/electron4/files/mixin-deep-1.3.2' selected='selected'>dependabot/npm_and_yarn/devel/electron4/files/mixin-deep-1.3.2</option>
<option value='main'>main</option>
<option value='master'>master</option>
<option value='svn_head'>svn_head</option>
</select> <input type='submit' value='switch'/></form></td></tr>
<tr><td class='sub'>FreeBSD Ports (https://github.com/freebsd/freebsd-ports)</td><td class='sub right'></td></tr></table>
<table class='tabs'><tr><td>
<a href='/~lantw44/cgit/cgit.cgi/freebsd-ports/about/?h=dependabot/npm_and_yarn/devel/electron4/files/mixin-deep-1.3.2'>about</a><a href='/~lantw44/cgit/cgit.cgi/freebsd-ports/?h=dependabot/npm_and_yarn/devel/electron4/files/mixin-deep-1.3.2'>summary</a><a href='/~lantw44/cgit/cgit.cgi/freebsd-ports/refs/?h=dependabot/npm_and_yarn/devel/electron4/files/mixin-deep-1.3.2&amp;id=6c3ba5754143d6ecbe70b51d4b72ad8d6e19e8af'>refs</a><a class='active' href='/~lantw44/cgit/cgit.cgi/freebsd-ports/log/net/ldapsh?h=dependabot/npm_and_yarn/devel/electron4/files/mixin-deep-1.3.2'>log</a><a href='/~lantw44/cgit/cgit.cgi/freebsd-ports/tree/net/ldapsh?h=dependabot/npm_and_yarn/devel/electron4/files/mixin-deep-1.3.2&amp;id=6c3ba5754143d6ecbe70b51d4b72ad8d6e19e8af'>tree</a><a href='/~lantw44/cgit/cgit.cgi/freebsd-ports/commit/net/ldapsh?h=dependabot/npm_and_yarn/devel/electron4/files/mixin-deep-1.3.2&amp;id=6c3ba5754143d6ecbe70b51d4b72ad8d6e19e8af'>commit</a><a href='/~lantw44/cgit/cgit.cgi/freebsd-ports/diff/net/ldapsh?h=dependabot/npm_and_yarn/devel/electron4/files/mixin-deep-1.3.2&amp;id=6c3ba5754143d6ecbe70b51d4b72ad8d6e19e8af'>diff</a><a href='/~lantw44/cgit/cgit.cgi/freebsd-ports/stats/net/ldapsh?h=dependabot/npm_and_yarn/devel/electron4/files/mixin-deep-1.3.2'>stats</a></td><td class='form'><form class='right' method='get' action='/~lantw44/cgit/cgit.cgi/freebsd-ports/log/net/ldapsh'>
<input type='hidden' name='h' value='dependabot/npm_and_yarn/devel/electron4/files/mixin-deep-1.3.2'/><input type='hidden' name='id' value='6c3ba5754143d6ecbe70b51d4b72ad8d6e19e8af'/><select name='qt'>
<option value='grep'>log msg</option>
<option value='author'>author</option>
<option value='committer'>committer</option>
<option value='range'>range</option>
</select>
<input class='txt' type='search' size='10' name='q' value=''/>
<input type='submit' value='search'/>
</form>
</td></tr></table>
<div class='path'>path: <a href='/~lantw44/cgit/cgit.cgi/freebsd-ports/log/?h=dependabot/npm_and_yarn/devel/electron4/files/mixin-deep-1.3.2&amp;id=6c3ba5754143d6ecbe70b51d4b72ad8d6e19e8af'>root</a>/<a href='/~lantw44/cgit/cgit.cgi/freebsd-ports/log/net?h=dependabot/npm_and_yarn/devel/electron4/files/mixin-deep-1.3.2&amp;id=6c3ba5754143d6ecbe70b51d4b72ad8d6e19e8af'>net</a>/<a href='/~lantw44/cgit/cgit.cgi/freebsd-ports/log/net/ldapsh?h=dependabot/npm_and_yarn/devel/electron4/files/mixin-deep-1.3.2&amp;id=6c3ba5754143d6ecbe70b51d4b72ad8d6e19e8af'>ldapsh</a></div><div class='content'><table class='list nowrap'><tr class='nohover'><th></th><th class='left'>Commit message (<a href='/~lantw44/cgit/cgit.cgi/freebsd-ports/log/net/ldapsh?h=dependabot/npm_and_yarn/devel/electron4/files/mixin-deep-1.3.2&amp;id=6c3ba5754143d6ecbe70b51d4b72ad8d6e19e8af&amp;showmsg=1'>Expand</a>)</th><th class='left'>Author</th><th class='left'>Age</th><th class='left'>Files</th><th class='left'>Lines</th></tr>
<tr><td class='commitgraph'>* </td><td><a href='/~lantw44/cgit/cgit.cgi/freebsd-ports/commit/net/ldapsh?h=dependabot/npm_and_yarn/devel/electron4/files/mixin-deep-1.3.2&amp;id=a9df13095e689ce73dab9241fe03be8f39410a91'>Convert to UCL &amp; cleanup pkg-message (categories n)</a></td><td>mat</td><td><span title='2019-08-14 16:48:50 +0800'>2019-08-14</span></td><td>1</td><td><span class='deletions'>-2</span>/<span class='insertions'>+6</span></td></tr>
<tr><td class='commitgraph'>* </td><td><a href='/~lantw44/cgit/cgit.cgi/freebsd-ports/commit/net/ldapsh?h=dependabot/npm_and_yarn/devel/electron4/files/mixin-deep-1.3.2&amp;id=52cc212b6d681d559527d3fad552eea749ea5fa8'>Reset MAINTAINER of flz's ports by his request</a></td><td>tobik</td><td><span title='2018-03-06 20:32:00 +0800'>2018-03-06</span></td><td>1</td><td><span class='deletions'>-1</span>/<span class='insertions'>+1</span></td></tr>
<tr><td class='commitgraph'>* </td><td><a href='/~lantw44/cgit/cgit.cgi/freebsd-ports/commit/net/ldapsh?h=dependabot/npm_and_yarn/devel/electron4/files/mixin-deep-1.3.2&amp;id=3a86918390be07c92b90945a07361c7c134c7591'>Rename all three p5-ReadLine-(Gnu,Perl,TTYtter) to their real names</a></td><td>mat</td><td><span title='2016-06-21 21:24:53 +0800'>2016-06-21</span></td><td>1</td><td><span class='deletions'>-1</span>/<span class='insertions'>+1</span></td></tr>
