'use strict'

const fs = require('fs')
const path = require('path')
const express = require('express')
const jade = require('jade')
const util = require('./util')
const rootPath = path.join(__dirname, '/../../..')

class CleverPackage {

  constructor (cleverCoreInstance, name) {

    this.cleverCoreInstance = cleverCoreInstance

    this.loadedPackage = cleverCoreInstance.pkgList.packageNamed(name)

    this.waiters = []

    if(!this.loadedPackage) {
      throw new Error(`Package with name ${name} is not loaded`)
    }

    this.name = this.loadedPackage.name.toLowerCase()

    this.viewsPath = `${rootPath}/app/packages/${this.name}/views`
    this.assetsPath = `${rootPath}/app/packages/${this.name}/assets/dist`

    // Attach CleverCore to pkg object
    this.CleverCore = this.cleverCoreInstance.getClass()

    // Router mounting  point
    this.mountPoint = null

    // Serve module assets folder
    this.cleverCoreInstance.resolve('app', app => {
      app.use(`/public/${this.name}`, express.static(this.assetsPath))
    })

  }

  render (view, opts) {
    return jade.renderFile(`${this.viewsPath}/${view}.jade`, opts)
  }

  attach (options) {
    if (options && options.where) {
      this.mountPoint = options.where
      return this
    }
    throw new Error('Attach method requires `option.where`')
  }

  routes (dependencies) {

    const pkgRoutesPath = this.loadedPackage.path('routes')

    const promise = new Promise ((yep, nope) => {
      fs.exists(pkgRoutesPath, exists => {
        yep(exists)
      })
    })
    .then(exists => {
      if (!exists) return
      return new Promise((yep, nope) => {
        fs
          .readdir(this.loadedPackage.path('routes'), (err, files) => {
            if (err) return nope(err)
            yep(files)
          })
      })
    })
    .then(files => {
      return new Promise((yep, nope) => {
        this.cleverCoreInstance.resolve('app', app => {
          const pkg = this
          this.cleverCoreInstance.resolve(dependencies.concat(function () {
            const args = Array.prototype.slice.call(arguments)
            files.forEach(file => {
              app.use(`/${pkg.mountPoint || pkg.name}`,
                require(`${pkgRoutesPath}/${file}`)([pkg].concat(args)))
            })
            yep(pkg)
          }))
        })
      })
    })

    this.waiters.push(promise)
    return this
  }

  models () {

    const db = this.cleverCoreInstance.db
    const pkgModelsPath = `${rootPath}/app/packages/${this.name}/models`

    const promise = new Promise((yep, nope) => {
      fs
        .exists(pkgModelsPath, exists => {
          yep(exists)
        })
    })
    .then(exists => {
      if (!exists) return Promise.resolve()
      return new Promise((yep, nope) => {
        fs
          .readdir(pkgModelsPath, (err, files) => {
            if (err) return nope(err)
            yep(files)
          })
      })
      .then(files => {
        files.filter(file => {
          return (file.indexOf('.') !== 0) && (file !== 'index.js')
        })
        .forEach(file => {
          const model = db.sequelize.import(path.join(pkgModelsPath, file))
          db[model.name] = model
        })

        Object.keys(db).forEach(modelName => {
          if ('associate' in db[modelName]) {
            db[modelName].associate(db)
          }
        })
      })
    })

    this.waiters.push(promise)
    return this

  }

  register () {
    Promise
      .all(this.waiters)
      .then(() => {
        return this.cleverCoreInstance.register(this.name, this)
      })
      .catch(console.error.bind(console))
  }

  getCleverCore () {
    return this.CleverCore
  }

}


module.exports = CleverPackage

@@ -1847,35 +1847,28 @@
 new Promise(
-(yep, nope)
+done
  =%3E %7B%0A      
@@ -1931,24 +1931,95 @@
     
-const pkg = this
+done(app)%0A        %7D)%0A      %7D)%0A      .then(app =%3E %7B%0A        return new Promise(done =%3E %7B
 %0A   
@@ -2081,19 +2081,13 @@
 cat(
-function ()
+() =%3E
  %7B%0A 
@@ -2210,19 +2210,20 @@
 use(%60/$%7B
-pkg
+this
 .mountPo
@@ -2229,19 +2229,20 @@
 oint %7C%7C 
-pkg
+this
 .name%7D%60,
@@ -2295,19 +2295,20 @@
 ile%7D%60)(%5B
-pkg
+this
 %5D.concat
@@ -2347,15 +2347,17 @@
     
-yep(pkg
+done(this
 )%0A  

Update CleverPackage class