const async = require('async');
const fs = require('fs');
const path = require('path');
const marked = require('marked');
const utils = require('../utils');
const request = require('request');
const ejs = require('ejs');
const he = require('he');

module.exports = (section, meta, callback) => {

  // Task flow control
  async.parallel([

    // Compile content for top level page
    async.apply((utils.isExternal(section.contentSrc)) ? getExternalContent : getContent, section),

    // Compile content for children if required
    (cb) => async.map(section.children, (page, cb) => {
      utils.isExternal(page.contentSrc) ? getExternalContent(page, cb) : getContent(page, cb)
    }, cb)

  ], done);

  function getPattern(str, data) {
    var filename = path.join(meta.patterns, str);
    var str = fs.readFileSync(filename, 'utf-8');
    return ejs.compile(str, { filename: filename })(data);
  }

  // Compile pattern template
  var snippet = function () {   
    var hasExtension = path.extname(arguments[0]);

    if(arguments[0].constructor === Array) {

      var templateArr = arguments[0].map((item) => {
        
        if (path.extname(item.template)) {
          return getPattern(item.template, item.data);
        } else {
          return item.template;
        }
        
      });

      var template = templateArr.join('\n\n');
    } else if (hasExtension) {

      var str = arguments[0];
      var data = arguments[1] || {};
      var template = getPattern(str, data);

    } else {
      template = arguments[0];
    }

    var output = `<div class="<%-styles['code-snippet']-%>">
<div class="<%-styles['code-preview']-%>">${template}</div>
<pre class="line-numbers"><code class="language-markup">${he.encode(template)}</code></pre>
</div>`;

    return output;
  }

  var render = function(str, data) {
    var hasExtension = path.extname(arguments[0]);

    if(arguments[0].constructor === Array) {
      var templateArr = arguments[0].map((item) => {
        if (path.extname(item.template)) {
          return getPattern(item.template, item.data);
        } else {
          return item.template;
        }
      });

      var template = templateArr.join('\n\n');
    } else if (hasExtension) {
      var str = arguments[0];
      var data = arguments[1] || {};
      var template = getPattern(str, data);
    }  else {
      template = arguments[0];
    }

    return template;
  } 

  // On complete handler
  function done(err, result) {
    if (err) {
      callback(err);
    } else {
      callback(null, section)
    }
  }


  function getContent(page, cb) {

    if(page.processor) {

      page.processorOutput.map((data, index) => {
        page.contentCompiled.push(utils.wrap(marked(data), 'section', `${page.key}-${index}`));
      });

      cb();

    } else {
      async.forEachOf(page.fileDependencies, (src, index, cb) => {
        fs.readFile(src, 'utf-8', (err, data) => {
          if (err) {
            cb(err);
          } else {
            page.contentCompiled[index] = utils.wrap(marked(ejs.render(data, { snippet: snippet, render: render })), 'section', `${page.key}-${index}`);
            cb();
          }
        });
      }, cb);
    }
  }

  function getExternalContent(page, cb) {
    request(page.contentSrc, function (error, response, data) {
      if (!error && response.statusCode === 200) {
        page.contentCompiled.push(utils.wrap(marked(data), 'section', `${page.key}`));
        cb();
      }
    });
  };

}