'use strict';

const { existsSync, readFileSync, readdirSync, statSync, createReadStream } = require('fs');
const { join } = require('path');
const { spawn } = require('child_process');
const Koa = require('koa');
const Router = require('@koa/router');
// const { open } = require('openurl');
const { copyThemeVariables } = require('../util');
const MD = new require('markdown-it')();

const srcDir = join(__dirname, '../../src');
const distDir = join(__dirname, '../../dist');
const buildDir = join(__dirname, '../../build');
let template = readFileSync(join(__dirname, 'template.tpl'), { encoding: 'utf-8' });

if (!existsSync(srcDir)) {
  throw new Error(`Cannot find ${srcDir}`);
}

const extraArg = process.argv.slice(2)[0];
if (!extraArg) {
  console.error('命令错误，请使用 \`tnpm run dev [theme:][component]\` 启动单一组件开发，例如：tnpm run dev blue:button');
  return;
}

let [ theme, targetComponent ] = extraArg.split(':');
if (!targetComponent) {
  targetComponent = theme;
  // 默认是蓝色主题
  theme = 'blue';
}

// copy theme variables
copyThemeVariables(srcDir, theme);

// set template theme
const THEME_PLACE_HOLDER = '{% theme %}';
template = template.replace(THEME_PLACE_HOLDER, theme);

/*
if (!existsSync(distDir)) {
  throw new Error(`Cannot find ${distDir}`);
}

if (!existsSync(buildDir)) {
  throw new Error(`Cannot find ${buildDir}, please run \`tnpm run build:docs\` first`);
}
*/

// 所有组件
const componentNames = readdirSync(srcDir)
  .filter(d => !d.startsWith('_'))
  .filter(d => statSync(join(srcDir, d)).isDirectory());

const PORT = 3001;
const CONTENT_PLACE_HOLDER = '{% content %}';

const app = new Koa();
const router = new Router();

router
  .get('/', ctx => {
    ctx.redirect('/demo/index');
  })
  .get('/dist/:staticFile', ctx => {
    const { staticFile } = ctx.params;
    renderStaticFile(ctx, distDir, staticFile);
  })
  .get('/build/:staticFile', ctx => {
    const { staticFile } = ctx.params;
    renderStaticFile(ctx, buildDir, staticFile);
  })
  .get('/build/:componentName/:staticFile', ctx => {
    const { componentName, staticFile } = ctx.params;
    renderStaticFile(ctx, buildDir, `${componentName}/${staticFile}`);
  })
  .get('/demo/index', ctx => {
    renderDemoIndex(ctx);
  })
  .get('/demo/:name', ctx => {
    renderComponentDemo(ctx);
  });

app
  .use(router.routes())
  .listen(PORT, () => {
    console.log(`demo server started, please visit: http://127.0.0.1:${PORT}/`);
    // open(`http://127.0.0.1:${PORT}/`);

    // if (targetComponent !== 'all') {
    // 启动webpack构建
    spawn('tnpm', [ 'run', 'build:docs' ], {
      cwd: join(srcDir, '..'),
      stdio: 'inherit',
      env: {
        ...process.env,
        B_DESIGN_COMPONENTS: targetComponent,
      },
    });
    // }
  });

function renderStaticFile(ctx, rootDir, staticFile) {
  const filePath = join(rootDir, staticFile);

  if (!existsSync(filePath)) {
    ctx.status = 404;
    return;
  }

  if (staticFile.lastIndexOf('.css') > -1) {
    ctx.type = 'css';
  } else if (staticFile.lastIndexOf('.js') > -1) {
    ctx.type = 'js';
  }

  ctx.body = createReadStream(filePath, { encoding: 'utf-8' });
}

function renderDemoIndex(ctx) {
  let content = '';
  content += `
      <h2>这是B-Design Demo首页，点击进入组件demo页。</h2>
    `;

  content += `
    <h3>当前主题：${theme}</h3>
  `;

  content += `
      <ul class="dir-list">
        ${componentNames.map(name => {
    return `
                  <li>
                    <a href='/demo/${name}'>${name}</a>
                  </li>
                `;
  }).join('')}
      </ul>
    `;

  ctx.type = 'html';
  ctx.body = template.replace(CONTENT_PLACE_HOLDER, content);
}

function renderComponentDemo(ctx) {
  const { name: componentName } = ctx.params;
  if (!componentNames.includes(componentName)) {
    ctx.status = 404;
    ctx.body = `Not found component ${componentName}`;
    return;
  }

  const md = join(srcDir, componentName, 'docs', 'demo.md');
  if (!existsSync(md)) {
    ctx.status = 404;
    ctx.body = `Cannot find ${md}`;
    return;
  }

  const regIncludeScript = /@include (['"])([\w-]*?)\1/g;
  let content = MD.render(readFileSync(md, { encoding: 'utf-8' }));
  let match;
  let count = 0;
    while (match = regIncludeScript.exec(content)) { // eslint-disable-line
    const matchStr = match[0];
    const scriptFileName = match[2];
    if (/^common/.test(scriptFileName)) {
      content = content.replace(matchStr, insertScript(componentName, scriptFileName));
    } else {
      content = content.replace(matchStr, insertScript(componentName, scriptFileName, ++count));
    }
  }
  ctx.type = 'html';
  ctx.body = template.replace(CONTENT_PLACE_HOLDER, content);
}

function insertScript(componentName, scriptFileName, count) {
  const ext = scriptFileName.endsWith('.js') ? '' : '.js';
  const scriptFile = join(buildDir, componentName, scriptFileName + ext);
  if (!existsSync(scriptFile)) {
    return `cannot find ${scriptFile}`;
  }

  return `
    ${count ? `<div id="${componentName}-demo-${count}"></div>` : ''}
    <script type="text/javascript" src="/build/${componentName}/${scriptFileName}${ext}" ></script>
  `;
}
