import blocker from 'weex-transformer/lib/blocker'
import templater from 'weex-templater'
import styler from 'weex-styler'
import scripter from 'weex-scripter'

import md5 from 'md5'

import { transformerVersion } from './config'
import {
  MODULE_EXPORTS_REG,
  REQUIRE_REG,
  FUNC_START_REG,
  FUNC_END_REG,
  getNameByPath,
  checkFileExist,
  depHasRequired,
  stringifyFunction,
  appendToWarn
} from './util'

export function parseWeex (loader, params, source, map, deps, elementName) {
  return new Promise(
    // separate source into <element>s, <template>, <style>s and <script>s
    separateBlocks(source, deps || []))
    // pre-parse non-javascript parts
    .then(preParseBlocks(loader, params, map))
    // join blocks together and parse as javascript finally
    .then(parseBlocks(loader, params, map, elementName))
}

function separateBlocks (source, deps) {
  return (resolve, reject) => {
    blocker.format(source, (err, ret) => {
      if (err) {
        reject(err)
      }
      else {
        ret.deps = deps
        resolve(ret)
      }
    })
  }
}

function preParseBlocks (loader, params, map) {
  return (blocks) => {
    const { deps, elements, template, styles, scripts, config, data } = blocks
    const promises = [
      Promise.resolve(),
      Promise.resolve(),
      Promise.resolve(),
      Promise.resolve(scripts),
      Promise.resolve(deps),
      Promise.resolve(config),
      Promise.resolve(data)
    ]
    let content
    // pre-parse sub elements
    if (elements) {
      const elPromises = []
      Object.keys(elements).forEach(key => {
        const el = elements[key]
        // record original positions of each <element>
        map.setElementPosition(el.name, el.line, el.column)
        elPromises.push(parseWeex(loader, params, el.content, map, deps, el.name))
      })
      promises[0] = Promise.all(elPromises)
    }
    // pre-parse template
    if (template) {
      content = template.content
      promises[1] = parseTemplate(loader, params, content, deps)
    }
    // pre-parse styles
    if (styles) {
      content = styles.reduce((pre, cur) => {
        return pre + '\n' + cur.content
      }, '')
      promises[2] = parseStyle(loader, params, content)
    }
    return Promise.all(promises)
  }
}

function parseBlocks (loader, params, map, elementName) {
  return (results) => {
    const elements = results[0] || []
    const template = results[1]
    const style = results[2]
    const scripts = results[3]
    const deps = results[4] || []
    const configResult = results[5]
    const dataResult = results[6]

    let content = ''
    let config = {}
    let data

    const mapOffset = { basic: 0, subs: [] }

    if (scripts) {
      // record original and generated position of each <script>
      // the generated content is begin with empty string
      // so later the template, styles and elements will be appended/prepended
      // and mapOffset.basic will record lines of prepended *required* content
      content += scripts.reduce((prev, next, i) => {
        // length of previous content
        const line = prev.split(/\r?\n/g).length + 1
        const column = 1
        const oriLine = next.line
        const oriColumn = next.column
        mapOffset.subs.push({
          original: { line: oriLine, column: oriColumn },
          generated: { line, column },
          // length of next content
          length: next.content.split(/\r?\n/g).length
        })
        return prev + '\n;' + next.content
      }, '')
    }

    let requireContent = ''
    if (deps.length) {
      requireContent += deps.map(dep =>
        depHasRequired(content, dep) ? 'require("' + dep + '");' : ''
      ).join('\n')
      if (requireContent) {
        // length of implicitly requires
        mapOffset.basic = requireContent.split(/\r?\n/g).length
        content = requireContent + '\n' + content
      }
    }

    if (template) {
      // append template content, not impact sourcemap
      content += '\n;module.exports.template = module.exports.template || {}' +
        '\n;Object.assign(module.exports.template, ' + template + ')'
    }

    if (style) {
      // append style content, not impact sourcemap
      content += '\n;module.exports.style = module.exports.style || {}' +
        '\n;Object.assign(module.exports.style, ' + style + ')'
    }

    // prepare entry config
    if (configResult) {
      config = new Function('return ' + configResult.content.replace(/\n/g, ''))()
    }
    config.transformerVersion = transformerVersion
    config = JSON.stringify(config, null, 2)

    // prepare entry data
    if (dataResult) {
      data = new Function('return ' + dataResult.content.replace(/\n/g, ''))()
      data = JSON.stringify(data, null, 2)
    }

    return parseScript(loader, params, content, { config, data, elementName, elements, map, mapOffset })
  }
}

export function parseTemplate (loader, params, source, deps) {
  return new Promise((resolve, reject) => {
    templater.parse(source, (err, obj) => {
      if (err) {
        reject(err)
      }
      else {
        appendToWarn(loader, obj.log)
        // push valid obj.deps to deps
        if (deps && obj.deps) {
          obj.deps.map(
            dep => checkFileExist(dep, params.resourcePath)
          ).forEach(dep => {
            if (dep) {
              deps.push(dep)
            }
          })
        }
        // parse json to string and treat function specially
        let target = JSON.stringify(obj.jsonTemplate, stringifyFunction, '  ')
        target = target.replace(FUNC_START_REG, '').replace(FUNC_END_REG, '')
        resolve(target)
      }
    })
  })
}

export function parseStyle (loader, params, source) {
  return new Promise((resolve, reject) => {
    styler.parse(source, (err, obj) => {
      if (err) {
        reject(err)
      }
      else {
        appendToWarn(loader, obj.log)
        resolve(JSON.stringify(obj.jsonStyle, null, 2))
      }
    })
  })
}

export function parseScript (loader, params, source, env) {
  const { config, data, elementName, elements, map, mapOffset } = env

  // the entry component has a special resource query and not a sub element tag
  const isEntry = params.resourceQuery.entry === true && !elementName

  // resolve component name
  const name = isEntry
    ? md5(source)
    : (elementName || params.resourceQuery.name || getNameByPath(params.resourcePath))

  // join with elements deps
  // 2 more lines between each element and the end
  map && map.start()
  const prefix = (elements || []).reduce((prev, next, index) => {
    const prevLength = prev.split(/\r?\n/g).length
    const nextLength = next.split(/\r?\n/g).length
    // record generated positions of each <element>
    map && map.addElement(name, index, prevLength, nextLength)
    return prev + next + ';\n\n'
  }, '')

  // fix data option from an object to a function
  let target = scripter.fix(source)

  // wrap with __weex_define__(name, [], (r, e, m) {...})
  // 1 more line at start, 1 more line at end
  target = target
      .replace(MODULE_EXPORTS_REG, '__weex_module__.exports')
      .replace(REQUIRE_REG, '__weex_require__($1$2$1)')
  target = ';__weex_define__("@weex-component/' + name + '", [], ' +
      'function(__weex_require__, __weex_exports__, __weex_module__)' +
      '{\n' + target + '\n})'

  // record mapOffset into sourcemap
  if (mapOffset) {
    // length of generated prefix (elements) and basic (implicitly requires)
    const preLines = prefix.split(/\r?\n/g).length + mapOffset.basic
    mapOffset.subs.forEach(info => {
      map.addScript(elementName || name, info, preLines)
    })
  }
  map && map.end()

  // append __weex_bootstrap__ for entry component
  // not impact sourcemap
  if (isEntry) {
    target += '\n;__weex_bootstrap__("@weex-component/' + name + '", ' +
        String(config) + ',' +
        String(data) + ')'
  }

  return Promise.resolve(prefix + target)
}

