
async = require 'async'
crypto = require 'crypto'
pathutil = require 'path'
mime = require 'mime'
{extend} = require './util'
{EventEmitter} = require 'events'

class exports.Asset extends EventEmitter
    defaultMaxAge: 60*60*24*365 # one year
    constructor: (options) ->
        super()
        options ?= {}
        @url = options.url if options.url?
        @contents = options.contents if options.contents?
        @headers = if options.headers then options.headers else {}
        headers = {}
        for key, value of @headers
            headers[key.toLowerCase()] = value
        @headers = headers
        @ext = pathutil.extname @url
        @mimetype = options.mimetype if options.mimetype?
        @mimetype ?= mime.types[@ext.slice(1, @ext.length)]
        @mimetype ?= 'text/plain'
        @hash = options.hash if options.hash?
        @maxAge = options.maxAge if options.maxAge?
        @allowNoHashCache = options.allowNoHashCache if options.allowNoHashCache?
        @on 'newListener', (event, listener) =>
            if event is 'complete' and @completed is true
                listener()
        @on 'created', (data) =>
            if data?.contents?
                @contents = data.contents
            if data?.assets?
                @assets = data.assets
            if @contents?
                @createSpecificUrl()
                @createHeaders()
            @completed = true
            @emit 'complete'
        @on 'error', (error) =>
            throw error if @listeners 'error' is 1
        @on 'start', =>
            @maxAge ?= @rack?.maxAge
            @maxAge ?= @defaultMaxAge unless @hash is false
            @allowNoHashCache ?= @rack?.allowNoHashCache
            @create options
        process.nextTick =>
            @maxAge ?= @defaultMaxAge
            return @create options unless @rack?

    respond: (request, response) ->
        headers = {}
        if request.url is @url and @allowNoHashCache isnt true
            for key, value of @headers
                headers[key] = value
            delete headers['cache-control']
        else
            headers = @headers
        for key, value of headers
            response.header key, value
        return response.send @contents
        
    checkUrl: (url) ->
        url is @specificUrl or (not @hash? and url is @url)

    handle: (request, response, next) ->
        handle = =>
            if @assets?
                for asset in @assets
                    if asset.checkUrl request.url
                        return asset.respond request, response
            if @checkUrl(request.url)
                @respond request, response
            else next()
        if @completed is true
            handle()
        else @on 'complete', ->
            handle()
        
    create: (options) ->
        @emit 'created'

    createHeaders: ->
        @headers['content-type'] ?= @mimetype
        #@headers['content-length'] = @contents.length
        if @maxAge?
            @headers['cache-control'] ?= "public, max-age=#{@maxAge}"

    tag: ->
        switch @mimetype
            when 'text/javascript'
                tag = "\n<script type=\"#{@mimetype}\" "
                return tag += "src=\"#{@specificUrl}\"></script>"
            when 'text/css'
                return "\n<link rel=\"stylesheet\" href=\"#{@specificUrl}\">"

    createSpecificUrl: ->
        @md5 = crypto.createHash('md5').update(@contents).digest 'hex'
        if @hash is false
            @useDefaultMaxAge = false
            return @specificUrl = @url
        @specificUrl = "#{@url.slice(0, @url.length - @ext.length)}-#{@md5}#{@ext}"
        if @hostname?
            @specificUrl = "//#{@hostname}#{@specificUrl}"
        
    isRelevantUrl: (specificUrl) ->
        baseUrl = @url.slice(0, @url.length - @ext.length)
        if specificUrl.indexOf baseUrl isnt -1 and @ext is pathutil.extname specificUrl
            return true
        return false

    @extend: extend
