import Context from 'skypager-registry/lib/context'
import Helper from '../helper'

export class DocumentType extends Helper {
  static isCacheable = true

  static dirname = __dirname
  
  static cacheable(setting = true) {
    return this.isCacheable = !!setting
  }

  static definedAt = __dirname

  static createRegistry = (options = {}) => new Context('documentTypes', {
    context: require.context('../document-types', false, /.js$/),
    ...options,
    sourceModule: {
      id: (module && module.id) || __filename,
      filename: __filename, dirname: __dirname,
      ...options.sourceModule || {},
    },
  })

  static attach(project, options = {}) {
    return Helper.attach(project, DocumentType, {
      registryProp: 'documentTypes',
      lookupProp: 'documentType',
      registry: options.registry || DocumentType.createRegistry(),
      ...options,
    })
  }

  get matchingDocuments() {
    return this.loadMatchingDocuments({ready: false})
  }

  loadMatchingDocuments(options = {}) {
    const { 
      ready = true,
      pattern = '*'
    } = options

    return this.project
      .route(pattern)
      .filter(r => this.testDocument(r.doc))
      .map(({doc}) =>  ready ? doc.ready : doc)
  }

  testDocument(doc) {
    return this.provider.testDocument(doc)
  }

  toAST(source, options = {}) {
    if (typeof source !== 'string' && typeof source === 'object' && typeof source.contents === 'string') {
      source = source.contents
    }   

    return this.provider.toAST(source, options)
  }

  compile(source, options = {}) {
    if (typeof source === 'object' && typeof source.ast === 'object' && typeof source.contents === 'string') {
      return {
        source: source.contents,
        ast: source.ast,
        compiled: this.provider.compile(source.contents, options),
        options,
      }
    } else if (typeof source !== 'string' && typeof source === 'object' && typeof source.contents === 'string') {
      source = source.contents

      const ast = this.toAST(source, options)

      return {
        source,
        ast,
        compiled: this.provider.compile(source, options),
        options,
      }
    } 
  }

  decorate(doc) {
    return this.provider.decorate(doc)
  }

  getTransforms() {
    return this.provider.getTransforms ? this.provider.getTransforms() : {}
  }
  
   markdownTransforms() {
      return {
        markdown: require('../transformers/markdown').default,
      }
    }

  markdownUtils() {
    return {
      filter: require('unist-util-filter'),
      findAfter: require('unist-util-find-after'),
      findAllAfter: require('unist-util-find-all-after'),
      findAllBefore: require('unist-util-find-all-before'),
      index: require('unist-util-index'),
      map: require('unist-util-map'),
      parents: require('unist-util-parents'),
      position: require('unist-util-position'),
      removePosition: require('unist-util-remove-position'),
      select: require('unist-util-select'),
      source: require('unist-util-source'),
      visit: require('unist-util-visit'),
      reporter: require('vfile-reporter'),
      toString: require('mdast-util-to-string'),
      docblockParser: require('docblock-parser'),
      headingRange: require('mdast-util-heading-range'),
      inject: require('mdast-util-inject'),
    }
  }
}

export default DocumentType

export const attach = DocumentType.attach
