fs = require 'fs'
path = require 'path'
YAML = require 'libyaml'
hb = require 'handlebars'
kss = require 'kss'
wrench = require 'wrench'
helpers = require 'handlebars-helpers'

module_path = path.join(path.dirname(fs.realpathSync(__filename)), '../');
console.log module_path
exports.Styleguide = class Styleguide

  constructor: (options) ->
    @kssOptions =
      mask: "*.scss"
      markdown: false
    @sgBlockTemplate = null
    @sgIndexTemplate = null
    @styleguideHTML = ""

    @sections = []
    @indexList = []
    @files = options

  registerHelpers: ->
    helpers.register(hb, {
      # TODO: add options block to grunt-sg?
    })

  getSGBlockTemplate: ->
    data = fs.readFileSync "#{module_path}views/_styleguide_block.hbs", 'utf8'
    @sgBlockTemplate = hb.compile data

  getSGHeaderTemplate: ->
    data = fs.readFileSync "#{module_path}/views/_header.hbs", "utf8"
    @sgHeaderTemplate = hb.compile data
    syntaxData = @files
    @sgHeaderCompiledTemplate = @sgHeaderTemplate syntaxData

  getSGFooterTemplate: ->
    data = fs.readFileSync "#{module_path}/views/_footer.hbs", "utf8"
    @sgFooterTemplate = hb.compile data
    jsData = @files
    @sgFooterCompiledTemplate = @sgFooterTemplate jsData

  getSGIndexTemplate: ->
    data = fs.readFileSync "#{module_path}views/_index.hbs", 'utf8'
    @sgIndexTemplate = hb.compile data

  registerHandlebarsPartial: (name, contents) ->
    hb.registerPartial name.replace(/\.hbs/, ""), contents

  registerHandlebarsPartials: ->
    for file in fs.readdirSync @files.html
      hbs = fs.readFileSync "#{@files.html}/#{file}", 'utf8'
      @registerHandlebarsPartial file, hbs

  generateStyleguideBlock: (file, styleguide) ->
    html = ""
    templateData = ""
    name = file.replace /\.[s]*css/, ""

    if @files.data
      htmlFile = "#{name}.hbs"
      ymlFile = "#{name}.yml"
    else
      htmlFile = "#{name}.html"

    try
      if @files.data
        hbs = fs.readFileSync "#{@files.html}/#{htmlFile}", 'utf8'
        if fs.existsSync "#{@files.data}/#{ymlFile}"
          templateData = YAML.readFileSync "#{@files.data}/#{ymlFile}", 'utf8'
          @blockTemplate = hb.compile hbs
        else
          @blockTemplate = hbs
      else
        plain_html = fs.readFileSync "#{@files.html}/#{htmlFile}", 'utf8'
        @blockTemplate = plain_html

    catch e
      if e.code != 'ENOENT'
        throw e;
      return

    if typeof @blockTemplate == "function"
      data =
        name: name
        file: file
        section: styleguide.data.sections[0].data
        html: @blockTemplate templateData[0]
    else
      data =
        name: name
        file: file
        section: styleguide.data.sections[0].data
        html: @blockTemplate

    section: data.section.reference
    html: @sgBlockTemplate data

  copyAssets: ->
    console.log "Copying assets from #{module_path}public to #{@files.dest}"
    wrench.copyDirSyncRecursive "#{module_path}public", @files.dest,
      forceDelete: true
      preserveFiles: false

  saveSG: ->
    console.log "Saving Styleguide..."

    @sections.sort (a, b) ->
      if parseInt(a.section, 10) > parseInt(b.section, 10) then 1 else -1

    output = @sgIndexTemplate @sections

    for section in @sections
      output += section.html

    finalHTML = @sgHeaderCompiledTemplate + output + @sgFooterCompiledTemplate

    @copyAssets()

    try
      fs.writeFileSync "#{@files.dest}/index.html", finalHTML
    catch e

    console.log "Styleguide generated successfully"

  parseCSS: (css_dir) ->
    for file in fs.readdirSync(css_dir)
      if (fs.lstatSync("#{css_dir}/#{file}").isDirectory())
        @parseCSS("#{css_dir}/#{file}")
      else
        css = fs.readFileSync "#{css_dir}/#{file}", 'utf8'
        kss.parse css, @kssOptions, (err, styleguide) =>
          throw err if err
          block = @generateStyleguideBlock(file, styleguide) if styleguide.data.sections.length > 0
          unless block == undefined
            block.name = file.replace /.scss/, ""
            @sections.push block

  generate: ->
    @registerHelpers()
    @getSGBlockTemplate()
    @getSGIndexTemplate()
    @getSGHeaderTemplate()
    @getSGFooterTemplate()

    if @files.data
      @registerHandlebarsPartials()

    console.log "Examining files in #{@files.css}..."
    @parseCSS(@files.css)

    @saveSG()