"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.createImportCode = createImportCode;
exports.exportInterface = exportInterface;
exports.exportType = exportType;
exports.formatBTreeMap = formatBTreeMap;
exports.formatCompact = formatCompact;
exports.formatResult = formatResult;
exports.formatOption = formatOption;
exports.formatTuple = formatTuple;
exports.formatVec = formatVec;
exports.formatType = formatType;
exports.indent = indent;
exports.FOOTER = exports.HEADER = void 0;

var _types = require("../../codec/types");

var _create = require("../../codec/create");

var _utils = require("../../codec/utils");

var _imports = require("./imports");

// Copyright 2017-2019 @polkadot/types authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
const HEADER = '// Auto-generated via `yarn build:interfaces`, do not edit\n/* eslint-disable @typescript-eslint/no-empty-interface */\n\n';
exports.HEADER = HEADER;
const FOOTER = '\n'; // creates the import lines

exports.FOOTER = FOOTER;

function createImportCode(header, checks) {
  return checks.reduce((result, _ref) => {
    let {
      file,
      types
    } = _ref;

    if (types.length) {
      result += "import { ".concat(types.sort().join(', '), " } from '").concat(file, "';\n");
    }

    return result;
  }, header) + '\n';
} // helper to generate a `export interface <Name> extends <Base> {<Body>}


function exportInterface() {
  let name = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
  let base = arguments.length > 1 ? arguments[1] : undefined;
  let body = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : '';
  return "/** ".concat(base, " */\nexport interface ").concat(name, " extends ").concat(base, " {").concat(body.length ? '\n' : '').concat(body, "}");
} // helper to create an `export type <Name> = <Base>`
// but since we don't want type alias (TS doesn't preserve names) we use
// interface here.


function exportType() {
  let name = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
  let base = arguments.length > 1 ? arguments[1] : undefined;
  return exportInterface(name, base);
}
/**
 * Given the inner `K` & `V`, return a `BTreeMap<K, V>`  string
 */


function formatBTreeMap(key, val) {
  return "BTreeMap<".concat(key, ", ").concat(val, ">");
}
/**
 * Given the inner `T`, return a `Compact<T>` string
 */


function formatCompact(inner) {
  return (0, _utils.paramsNotation)('Compact', inner);
}
/**
 * Given the inner `O` & `E`, return a `Result<O, E>`  string
 */


function formatResult(innerOk, innerError) {
  return "Result<".concat(innerOk, ", ").concat(innerError, ">");
}
/**
 * Given the inner `T`, return a `Option<T>` string
 */


function formatOption(inner) {
  return (0, _utils.paramsNotation)('Option', inner);
}
/**
 * Given the inners `T[]`, return a `ITuple<...T>` string
 */


function formatTuple(inners) {
  return (0, _utils.paramsNotation)('ITuple', "[".concat(inners.join(', '), "]"));
}
/**
 * Given the inner `T`, return a `Vec<T>` string
 */


function formatVec(inner) {
  return (0, _utils.paramsNotation)('Vec', inner);
}
/**
 * Correctly format a given type
 */


function formatType(type, imports) {
  let typeDef;

  if (typeof type === 'string') {
    typeDef = (0, _create.getTypeDef)(type);
  } else {
    typeDef = type;
  }

  switch (typeDef.info) {
    case _types.TypeDefInfo.Compact:
      {
        return formatCompact(formatType(typeDef.sub.type, imports));
      }

    case _types.TypeDefInfo.Option:
      {
        return formatOption(formatType(typeDef.sub.type, imports));
      }

    case _types.TypeDefInfo.Plain:
      {
        return typeDef.type;
      }

    case _types.TypeDefInfo.Vec:
      {
        return formatVec(formatType(typeDef.sub.type, imports));
      }

    case _types.TypeDefInfo.Tuple:
      {
        (0, _imports.setImports)(imports, ['ITuple']); // `(a,b)` gets transformed into `ITuple<[a, b]>`

        return formatTuple(typeDef.sub.map(sub => formatType(sub.type, imports)));
      }

    case _types.TypeDefInfo.VecFixed:
      {
        (0, _imports.setImports)(imports, ['U8a']); // `[u8, 32]` gets transformed into U8a

        return 'U8a';
      }

    default:
      {
        throw new Error("Cannot format ".concat(type, "."));
      }
  }
}
/**
 * Indent a string with `n` spaces before.
 */


function indent(n) {
  let char = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ' ';
  return function (str) {
    return "".concat(char.repeat(n)).concat(str);
  };
}