/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

'use strict'

const fqn = require('./fqn')
const fs = require('fs')
const util = require('util')

const version = require('./package.json').version

const isObject = obj => typeof obj === 'object' && obj !== null && !Array.isArray(obj)

// error class
class ComposerError extends Error {
  constructor (message, argument) {
    super(message + (argument !== undefined ? '\nArgument value: ' + util.inspect(argument) : ''))
  }
}

const composer = { util: { declare, version } }

const lowerer = {
  literal (value) {
    return composer.let({ value }, () => value)
  },

  retain (...components) {
    let params = null
    return composer.let(
      { params },
      composer.finally(
        args => { params = args },
        composer.seq(composer.mask(...components),
          result => ({ params, result }))))
  },

  retain_catch (...components) {
    return composer.seq(
      composer.retain(
        composer.finally(
          composer.seq(...components),
          result => ({ result }))),
      ({ params, result }) => ({ params, result: result.result }))
  },

  if (test, consequent, alternate) {
    let params = null
    return composer.let(
      { params },
      composer.finally(
        args => { params = args },
        composer.if_nosave(
          composer.mask(test),
          composer.finally(() => params, composer.mask(consequent)),
          composer.finally(() => params, composer.mask(alternate)))))
  },

  while (test, body) {
    let params = null
    return composer.let(
      { params },
      composer.finally(
        args => { params = args },
        composer.seq(composer.while_nosave(
          composer.mask(test),
          composer.finally(() => params, composer.seq(composer.mask(body), args => { params = args }))),
        () => params)))
  },

  dowhile (body, test) {
    let params = null
    return composer.let(
      { params },
      composer.finally(
        args => { params = args },
        composer.seq(composer.dowhile_nosave(
          composer.finally(() => params, composer.seq(composer.mask(body), args => { params = args })),
          composer.mask(test)),
        () => params)))
  },

  repeat (count, ...components) {
    return composer.let(
      { count },
      composer.while(
        () => count-- > 0,
        composer.mask(...components)))
  },

  retry (count, ...components) {
    return composer.let(
      { count },
      params => ({ params }),
      composer.dowhile(
        composer.finally(({ params }) => params, composer.mask(composer.retain_catch(...components))),
        ({ result }) => result.error !== undefined && count-- > 0),
      ({ result }) => result)
  },

  merge (...components) {
    return composer.seq(composer.retain(...components), ({ params, result }) => Object.assign(params, result))
  }
}

// apply f to all fields of type composition
function visit (composition, f) {
  composition = Object.assign({}, composition) // copy
  const combinator = composition['.combinator']()
  if (combinator.components) {
    composition.components = composition.components.map(f)
  }
  for (let arg of combinator.args || []) {
    if (arg.type === undefined && composition[arg.name] !== undefined) {
      composition[arg.name] = f(composition[arg.name], arg.name)
    }
  }
  return new Composition(composition)
}

// recursively label combinators with the json path
function label (composition) {
  const label = path => (composition, name, array) => {
    const p = path + (name !== undefined ? (array === undefined ? `.${name}` : `[${name}]`) : '')
    composition = visit(composition, label(p)) // copy
    composition.path = p
    return composition
  }
  return label('')(composition)
}

// derive combinator methods from combinator table
// check argument count and map argument positions to argument names
// delegate to Composition constructor for the rest of the validation
function declare (combinators, prefix) {
  if (arguments.length > 2) throw new ComposerError('Too many arguments in "declare"')
  if (!isObject(combinators)) throw new ComposerError('Invalid argument "combinators" in "declare"', combinators)
  if (prefix !== undefined && typeof prefix !== 'string') throw new ComposerError('Invalid argument "prefix" in "declare"', prefix)
  const composer = {}
  for (let key in combinators) {
    const type = prefix ? prefix + '.' + key : key
    const combinator = combinators[key]
    if (!isObject(combinator) || (combinator.args !== undefined && !Array.isArray(combinator.args))) {
      throw new ComposerError(`Invalid "${type}" combinator specification in "declare"`, combinator)
    }
    for (let arg of combinator.args || []) {
      if (typeof arg.name !== 'string') throw new ComposerError(`Invalid "${type}" combinator specification in "declare"`, combinator)
    }
    composer[key] = function () {
      const composition = { type, '.combinator': () => combinator }
      const skip = (combinator.args && combinator.args.length) || 0
      if (!combinator.components && (arguments.length > skip)) {
        throw new ComposerError(`Too many arguments in "${type}" combinator`)
      }
      for (let i = 0; i < skip; ++i) {
        composition[combinator.args[i].name] = arguments[i]
      }
      if (combinator.components) {
        composition.components = Array.prototype.slice.call(arguments, skip)
      }
      return new Composition(composition)
    }
  }
  return composer
}

// composition class
class Composition {
  // weaker instanceof to tolerate multiple instances of this class
  static [Symbol.hasInstance] (instance) {
    return instance.constructor && instance.constructor.name === Composition.name
  }

  // construct a composition object with the specified fields
  constructor (composition) {
    const combinator = composition['.combinator']()
    Object.assign(this, composition)
    for (let arg of combinator.args || []) {
      if (composition[arg.name] === undefined && arg.optional && arg.type !== undefined) continue
      switch (arg.type) {
        case undefined:
          try {
            this[arg.name] = composer.task(arg.optional ? composition[arg.name] || null : composition[arg.name])
          } catch (error) {
            throw new ComposerError(`Invalid argument "${arg.name}" in "${composition.type} combinator"`, composition[arg.name])
          }
          break
        case 'name':
          try {
            this[arg.name] = fqn(composition[arg.name])
          } catch (error) {
            throw new ComposerError(`${error.message} in "${composition.type} combinator"`, composition[arg.name])
          }
          break
        case 'value':
          if (typeof composition[arg.name] === 'function' || composition[arg.name] === undefined) {
            throw new ComposerError(`Invalid argument "${arg.name}" in "${composition.type} combinator"`, composition[arg.name])
          }
          break
        case 'object':
          if (!isObject(composition[arg.name])) {
            throw new ComposerError(`Invalid argument "${arg.name}" in "${composition.type} combinator"`, composition[arg.name])
          }
          break
        default:
          if ('' + typeof composition[arg.name] !== arg.type) {
            throw new ComposerError(`Invalid argument "${arg.name}" in "${composition.type} combinator"`, composition[arg.name])
          }
      }
    }
    if (combinator.components) this.components = (composition.components || []).map(obj => composer.task(obj))
    return this
  }

  // compile composition
  compile () {
    if (arguments.length > 0) throw new ComposerError('Too many arguments in "compile"')

    const actions = []

    const flatten = composition => {
      composition = visit(composition, flatten)
      if (composition.type === 'action' && composition.action) {
        actions.push({ name: composition.name, action: composition.action })
        delete composition.action
      }
      return composition
    }

    const obj = { composition: label(flatten(this)).lower(), ast: this, version }
    if (actions.length > 0) obj.actions = actions
    return obj
  }

  // recursively lower combinators to the desired set of combinators (including primitive combinators)
  lower (combinators = []) {
    if (arguments.length > 1) throw new ComposerError('Too many arguments in "lower"')
    if (!Array.isArray(combinators)) throw new ComposerError('Invalid argument "combinators" in "lower"', combinators)

    const lower = composition => {
      // repeatedly lower root combinator
      while (composition['.combinator']().def) {
        const path = composition.path
        const combinator = composition['.combinator']()
        if (Array.isArray(combinators) && combinators.indexOf(composition.type) >= 0) break
        // map argument names to positions
        const args = []
        const skip = (combinator.args && combinator.args.length) || 0
        for (let i = 0; i < skip; i++) args.push(composition[combinator.args[i].name])
        if (combinator.components) args.push(...composition.components)
        composition = combinator.def(...args)
        if (path !== undefined) composition.path = path // preserve path
      }
      // lower nested combinators
      return visit(composition, lower)
    }

    return lower(this)
  }
}

// primitive combinators
const combinators = {
  sequence: { components: true },
  if_nosave: { args: [{ name: 'test' }, { name: 'consequent' }, { name: 'alternate', optional: true }] },
  while_nosave: { args: [{ name: 'test' }, { name: 'body' }] },
  dowhile_nosave: { args: [{ name: 'body' }, { name: 'test' }] },
  try: { args: [{ name: 'body' }, { name: 'handler' }] },
  finally: { args: [{ name: 'body' }, { name: 'finalizer' }] },
  let: { args: [{ name: 'declarations', type: 'object' }], components: true },
  mask: { components: true },
  action: { args: [{ name: 'name', type: 'name' }, { name: 'action', type: 'object', optional: true }] },
  function: { args: [{ name: 'function', type: 'object' }] },
  async: { components: true }
}

Object.assign(composer, declare(combinators))

// derived combinators
const extra = {
  empty: { def: composer.sequence },
  seq: { components: true, def: composer.sequence },
  if: { args: [{ name: 'test' }, { name: 'consequent' }, { name: 'alternate', optional: true }], def: lowerer.if },
  while: { args: [{ name: 'test' }, { name: 'body' }], def: lowerer.while },
  dowhile: { args: [{ name: 'body' }, { name: 'test' }], def: lowerer.dowhile },
  repeat: { args: [{ name: 'count', type: 'number' }], components: true, def: lowerer.repeat },
  retry: { args: [{ name: 'count', type: 'number' }], components: true, def: lowerer.retry },
  retain: { components: true, def: lowerer.retain },
  retain_catch: { components: true, def: lowerer.retain_catch },
  value: { args: [{ name: 'value', type: 'value' }], def: lowerer.literal },
  literal: { args: [{ name: 'value', type: 'value' }], def: lowerer.literal },
  merge: { components: true, def: lowerer.merge }
}

Object.assign(composer, declare(extra))

// add or override definitions of some combinators
Object.assign(composer, {
  // detect task type and create corresponding composition object
  task (task) {
    if (arguments.length > 1) throw new ComposerError('Too many arguments in "task" combinator')
    if (task === undefined) throw new ComposerError('Invalid argument in "task" combinator', task)
    if (task === null) return composer.empty()
    if (task instanceof Composition) return task
    if (typeof task === 'function') return composer.function(task)
    if (typeof task === 'string') return composer.action(task)
    throw new ComposerError('Invalid argument "task" in "task" combinator', task)
  },

  // function combinator: stringify function code
  function (fun) {
    if (arguments.length > 1) throw new ComposerError('Too many arguments in "function" combinator')
    if (typeof fun === 'function') {
      fun = `${fun}`
      if (fun.indexOf('[native code]') !== -1) throw new ComposerError('Cannot capture native function in "function" combinator', fun)
    }
    if (typeof fun === 'string') {
      fun = { kind: 'nodejs:default', code: fun }
    }
    if (!isObject(fun)) throw new ComposerError('Invalid argument "function" in "function" combinator', fun)
    return new Composition({ type: 'function', function: { exec: fun }, '.combinator': () => combinators.function })
  },

  // action combinator
  action (name, options = {}) {
    if (arguments.length > 2) throw new ComposerError('Too many arguments in "action" combinator')
    if (!isObject(options)) throw new ComposerError('Invalid argument "options" in "action" combinator', options)
    let exec
    if (Array.isArray(options.sequence)) { // native sequence
      exec = { kind: 'sequence', components: options.sequence.map(fqn) }
    } else if (typeof options.filename === 'string') { // read action code from file
      exec = fs.readFileSync(options.filename, { encoding: 'utf8' })
    } else if (typeof options.action === 'function') { // capture function
      exec = `const main = ${options.action}`
      if (exec.indexOf('[native code]') !== -1) throw new ComposerError('Cannot capture native function in "action" combinator', options.action)
    } else if (typeof options.action === 'string' || isObject(options.action)) {
      exec = options.action
    }
    if (typeof exec === 'string') {
      exec = { kind: 'nodejs:default', code: exec }
    }
    const composition = { type: 'action', name, '.combinator': () => combinators.action }
    if (exec) composition.action = { exec }
    return new Composition(composition)
  },

  // recursively deserialize composition
  parse (composition) {
    if (arguments.length > 1) throw new ComposerError('Too many arguments in "parse" combinator')
    if (!isObject(composition)) throw new ComposerError('Invalid argument "composition" in "parse" combinator', composition)
    const combinator = typeof composition['.combinator'] === 'function' ? composition['.combinator']() : combinators[composition.type]
    if (!isObject(combinator)) throw new ComposerError('Invalid composition type in "parse" combinator', composition)
    return visit(Object.assign({ '.combinator': () => combinator }, composition), composition => composer.parse(composition))
  }
})

module.exports = composer
