"use strict";
var __extends = (this && this.__extends) || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
var path_1 = require("path");
var utility_1 = require("../../lib/utility");
var MAX_CODE_LEN = 50;
// const MAX_COMMENT_LEN = 80;
var SchemaPlugin = (function (_super) {
    __extends(SchemaPlugin, _super);
    function SchemaPlugin() {
        return _super !== null && _super.apply(this, arguments) || this;
    }
    SchemaPlugin.prototype.getHeaders = function () {
        return [
            '<link href="https://fonts.googleapis.com/css?family=Ubuntu+Mono:400,700" rel="stylesheet">',
            '<link type="text/css" rel="stylesheet" href="./assets/code.css" />',
        ];
    };
    SchemaPlugin.prototype.getAssets = function () {
        return [
            path_1.resolve(__dirname, 'code.css')
        ];
    };
    SchemaPlugin.prototype.getDocuments = function (buildForType) {
        var code = this.code(buildForType);
        if (code)
            return [{
                    title: 'GraphQL Schema definition',
                    description: utility_1.html.code(code)
                }];
        return [];
    };
    SchemaPlugin.prototype.code = function (buildForType) {
        if (!buildForType)
            return this.schema(this.document);
        var directive = this.document
            .directives
            .find(function (directive) { return directive.name === buildForType; });
        if (directive)
            return this.directive(directive);
        var type = this.document
            .types
            .find(function (type) { return type.name === buildForType; });
        if (type) {
            switch (type.kind) {
                case utility_1.SCALAR:
                    return this.scalar(type);
                case utility_1.OBJECT:
                    return this.object(type);
                case utility_1.INTERFACE:
                    return this.interfaces(type);
                case utility_1.UNION:
                    return this.union(type);
                case utility_1.ENUM:
                    return this.enum(type);
                case utility_1.INPUT_OBJECT:
                    return this.inputObject(type);
            }
        }
        throw new TypeError('Unexpected type: ' + buildForType);
    };
    SchemaPlugin.prototype.arguments = function (fieldOrDirectives) {
        var _this = this;
        if (fieldOrDirectives.args.length === 0) {
            return '';
        }
        return '(' +
            fieldOrDirectives
                .args
                .map(function (arg) { return _this.inputValue(arg); })
                .join(', ') +
            ')';
    };
    SchemaPlugin.prototype.argumentDescription = function (arg) {
        var desc = arg.description === null ?
            '[' + utility_1.html.highlight('NULL') + ']' : arg.description;
        return this.description(utility_1.html.highlight(arg.name) + ': ' + desc);
    };
    SchemaPlugin.prototype.argumentsDescription = function (fieldOrDirectives) {
        var _this = this;
        if (fieldOrDirectives.args.length === 0) {
            return [];
        }
        var reduceArguments = function (descriptions, arg) { return descriptions.concat(_this.argumentDescription(arg)); };
        return fieldOrDirectives.args
            .reduce(reduceArguments, [utility_1.html.comment('Arguments')]);
    };
    SchemaPlugin.prototype.deprecated = function (fieldOrEnumVal) {
        if (!fieldOrEnumVal.isDeprecated)
            return '';
        if (!fieldOrEnumVal.deprecationReason) {
            return utility_1.html.keyword('@deprecated');
        }
        return utility_1.html.keyword('@deprecated')
            + '( reason: ' + utility_1.html.value('"' + fieldOrEnumVal.deprecationReason + '" ') + ' )';
    };
    SchemaPlugin.prototype.description = function (description) {
        if (description)
            return utility_1.split(description, MAX_CODE_LEN)
                .map(function (descriptionLine) { return utility_1.html.comment(descriptionLine); });
        return [];
    };
    SchemaPlugin.prototype.directive = function (directive) {
        return utility_1.html.line(utility_1.html.keyword('directive') + ' ' +
            utility_1.html.keyword('@' + directive.name) + this.arguments(directive) + ' on ' +
            directive.locations.map(function (location) { return utility_1.html.keyword(location); }).join(' | '));
    };
    SchemaPlugin.prototype.enum = function (type) {
        var _this = this;
        var reduceEnumValues = function (lines, enumValue) { return lines
            .concat([''], _this.description(enumValue.description), [utility_1.html.property(enumValue.name) + _this.deprecated(enumValue)]); };
        return utility_1.html.line(utility_1.html.keyword('enum') + ' ' + utility_1.html.identifier(type) + ' {') +
            type.enumValues
                .reduce(reduceEnumValues, [])
                .map(function (line) { return utility_1.html.line(utility_1.html.tab(line)); })
                .join('') +
            utility_1.html.line('}');
    };
    SchemaPlugin.prototype.field = function (field) {
        var fieldDescription = this.description(field.description);
        var argumentsDescription = this.argumentsDescription(field);
        if (fieldDescription.length > 0 && argumentsDescription.length)
            fieldDescription.push(utility_1.html.comment(''));
        return []
            .concat(fieldDescription)
            .concat(argumentsDescription)
            .concat([
            utility_1.html.property(field.name) + this.arguments(field) + ': ' +
                utility_1.html.useIdentifier(field.type, this.url(field.type)) + ' ' + this.deprecated(field)
        ])
            .map(function (line) { return utility_1.html.line(utility_1.html.tab(line)); })
            .join('');
    };
    SchemaPlugin.prototype.fields = function (type) {
        var _this = this;
        return utility_1.html.line('') +
            type.fields
                .map(function (field) { return _this.field(field); })
                .join(utility_1.html.line(''));
    };
    SchemaPlugin.prototype.inputObject = function (type) {
        return utility_1.html.line(utility_1.html.keyword('input') + ' ' + utility_1.html.identifier(type) + ' {') +
            this.inputValues(type.inputFields) +
            utility_1.html.line('}');
    };
    SchemaPlugin.prototype.inputValues = function (inputValues) {
        var _this = this;
        return inputValues
            .map(function (inputValue) { return utility_1.html.line(_this.inputValue(inputValue)); })
            .join(utility_1.html.line(''));
    };
    SchemaPlugin.prototype.inputValue = function (arg) {
        var defaultValue = arg.defaultValue ?
            ' = ' + utility_1.html.value(arg.defaultValue) : '';
        return utility_1.html.parameter(arg) + ': ' + utility_1.html.useIdentifier(arg.type, this.url(arg.type)) + defaultValue;
    };
    SchemaPlugin.prototype.interfaces = function (type) {
        return utility_1.html.line(utility_1.html.keyword('interface') + ' ' + utility_1.html.identifier(type) + ' {') +
            this.fields(type) +
            utility_1.html.line('}');
    };
    SchemaPlugin.prototype.object = function (type) {
        var _this = this;
        var interfaces = type.interfaces
            .map(function (i) { return utility_1.html.useIdentifier(i, _this.url(i)); })
            .join(', ');
        var implemente = interfaces.length === 0 ? '' :
            ' ' + utility_1.html.keyword('implements') + ' ' + interfaces;
        return utility_1.html.line(utility_1.html.keyword('type') + ' ' + utility_1.html.identifier(type) + implemente + ' {') +
            this.fields(type) +
            utility_1.html.line('}');
    };
    SchemaPlugin.prototype.scalar = function (type) {
        return utility_1.html.line(utility_1.html.keyword('scalar') + ' ' + utility_1.html.identifier(type));
    };
    SchemaPlugin.prototype.schema = function (schema) {
        var definition = utility_1.html.line(utility_1.html.keyword('schema') + ' {');
        if (schema.queryType)
            definition += utility_1.html.line('') +
                this.description(schema.queryType.description)
                    .map(function (line) { return utility_1.html.line(utility_1.html.tab(line)); })
                    .join('') +
                utility_1.html.line(utility_1.html.tab(utility_1.html.property('query') + ': ' + utility_1.html.useIdentifier(schema.queryType, this.url(schema.queryType))));
        if (schema.mutationType)
            definition += utility_1.html.line('') +
                this.description(schema.mutationType.description)
                    .map(function (line) { return utility_1.html.line(utility_1.html.tab(line)); })
                    .join('') +
                utility_1.html.line(utility_1.html.tab(utility_1.html.property('mutation') + ': ' + utility_1.html.useIdentifier(schema.mutationType, this.url(schema.queryType))));
        if (schema.subscriptionType)
            definition += utility_1.html.line('') +
                this.description(schema.subscriptionType.description)
                    .map(function (line) { return utility_1.html.line(utility_1.html.tab(line)); })
                    .join('') +
                utility_1.html.line(utility_1.html.tab(utility_1.html.property('suscription') + ': ' + utility_1.html.useIdentifier(schema.subscriptionType, this.url(schema.queryType))));
        definition += utility_1.html.line('}');
        return [definition]
            .join(utility_1.html.line(''));
        /* return [this.schemaDefinition(schema)]
             .concat(
             directives.map(directive => this.directive(directive)),
             types.map((type) => this.type(type) as string)
             )
             .join('\n\n') + '\n';*/
    };
    SchemaPlugin.prototype.union = function (type) {
        var _this = this;
        return utility_1.html.line(utility_1.html.keyword('union') + ' ' + utility_1.html.identifier(type) + ' = ' +
            type.possibleTypes
                .map(function (type) { return utility_1.html.useIdentifier(type, _this.url(type)); })
                .join(' | '));
    };
    return SchemaPlugin;
}(utility_1.Plugin));
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = SchemaPlugin;
