const parseArgs = require('minimist');
const fs = require('fs');
const assert = require('assert');
const util = require('util');
const { resolve } = require('path');

const IDENT = '    ';

class MyDoc {

  constructor() {
    this.workDir = './';
  }

  async init() {
    await this.convert();
  }

  async convert() {
    this.env = fs.readFileSync(`${this.workDir}env.json`, 'utf8');
    this.data = `
<?php

class Doc
{

`;
    if (fs.existsSync(`${this.workDir}README.php`)) {
      this.data += fs.readFileSync(`${this.workDir}README.php`, 'utf8');
    }
    const files = fs.readdirSync('./', {encoding:'utf8', withFileTypes:true});
    files.forEach((item) => {
      if (item.name.slice(-3) == '.js' &&
          item.name != 'common.js') {
        const c = require(resolve('./') + '/' + item.name.slice(0, -3));
        this.convertClass(new c());
      }
    });
    this.data += `\n}`;
    console.log(this.data);
  }

  convertClass(c) {
    c.apis.forEach(
      (item) => {
        const method = item.method ? 'GET' : item.method;
        this.data += `
    /**
      * @api {${method}} ${item.url}  ${item.name}
      * @apiPermission none
      * @apiGroup ${item.group}
      * @apiVersion 1.0.0
      * @apiDescription ${item.desc}
`;
        const headers = [];
        if (item.hasOwnProperty('header')) {
          item['header'].forEach(
            (item) => {
              headers.push(item);
            }
          );
        } else {
          const common = require(resolve('./common'));
          headers.push(new common.DefaultHttpHeader());
        }
        headers.forEach(
          (header) => {
            header.fields.forEach(
              (field) => {
                this.data += `      * @apiHeader {String} ${field[0]} ${field[1]}\n`;
              }
            );
          }
        );
        if (item.hasOwnProperty('uri_params')) {
          this.asParamOut(item.uri_params, 'uri参数');
        }
        if (item.is_json_params) {
          this.data += `      * @apiParamExample {json} 请求样例:\n`;
          this.data += `      *     {\n`;
          this.asJsonOut(item.params, 1);
          this.data += `      *     }\n`;
        } else {
          this.asParamOut(item.params);
        }
        this.data += '     * @apiSuccessExample {json} Success-Response:\n';
        this.data += `     *     HTTP/1.1 200 OK\n`;
        this.data += `     *     {\n`;
        this.asJsonOut(item.response, 1);
        this.data += `     *     }\n`;
        this.data += `     */
`;
      }
    );
  }

  getFieldType(val) {
    if (typeof val == 'string') {
      return 'String';
    } else if (typeof val == 'number') {
      return 'Number';
    }
    return 'String';
  }

  asParamOut(itemList, group = null) {
      itemList.forEach(
        (item) => {
          if (util.isArray(item)) {
            const paramType = this.getFieldType(item[1]);
            const isOptional = item.length > 3 ? item[3].indexOf('optional') >= 0: false;
            if (group) {
              if (isOptional) {
                this.data += `      * @apiParam (${group}) {${paramType}} [${item[0]}] ${item[2]}\n`;
              } else {
                this.data += `      * @apiParam (${group}) {${paramType}} ${item[0]} ${item[2]}\n`;
              }
            } else {
              if (isOptional) {
                this.data += `      * @apiParam {${paramType}} [${item[0]}] ${item[2]}\n`;
              } else {
                this.data += `      * @apiParam {${paramType}} ${item[0]} ${item[2]}\n`;
              }
            }
          } else {
            this.asParamOut(item.fields, group);
          }
        }
      );
  }

  getJsonValue(val) {
    if (typeof val == 'number') {
      return 0;
    } else {
      return '""';
    }
  }

  asJsonOut(itemList, ident) {
      itemList.forEach(
        (item) => {
          const curIdent = (new Array(ident * 4)).fill(' ').join('');
          if (util.isArray(item[1])) {
            if (item[0].slice(0,1) == '!') {
              this.data += `      *     ${curIdent}"${item[0].slice(1)}": [ // struct ${item[2]}\n`;
              if (item[1].length == 1) {
                if (['string', 'number'].indexOf(typeof item[1][0]) >= 0) {
                  this.data += `     *     ${curIdent + IDENT}${this.getJsonValue(item[1])}\n`;
                } else {
                  this.data += `     *     ${curIdent + IDENT}{\n`;
                  this.asJsonOut(item[1][0].fields, ident + 2);
                  this.data += `     *     ${curIdent + IDENT}}\n`;
                }
              } else {
              }
              this.data += `     *     ${curIdent}]\n`;
            } else {
              this.data += `     *     ${curIdent}"${item[0]}": { // struct ${item[2]}\n`;
            }
          } else {
            if (util.isArray(item)) {
              if (['string', 'number'].indexOf(typeof item[1]) >= 0) {
                const paramType = this.getFieldType(item[1]);
                this.data += `     *     ${curIdent}"${item[0]}": ${this.getJsonValue(item[1])}, //${item[2]}\n`;
              } else {
                this.data += `     *     ${curIdent}"{item[0]}": { // struct ${item[1].constructor.name} ${item[2]}\n`;
                this.asJsonOut(item[1].fields, ident + 1);
                this.data += `     *     ${curIdent}}\n`;
              }
            } else if (typeof item == 'object'){
              this.asJsonOut(item.fields, ident);
            }
          }
        }
      );
  }

}

(new MyDoc).init();
