if (typeof module is 'object' and typeof define isnt 'function')
  if window? && window.nodeRequire?
    conda = nodeRequire 'conda'
  else
    conda = require 'conda'
else
  conda = window.conda

# Pass in the conda API context and the Backbone library
conda.backbone = (context, Backbone) ->
  # Utility functions

  convert = (text) ->
    if text.match /\d+/
      parseInt text, 10
    else
      text

  key = (text) ->
    text.split(/(\d+)/).map(convert).filter (x) -> x isnt ""

  naturalSortComparator = (a, b) ->
    a = key(a.get('name'))
    b = key(b.get('name'))

    for pair in _.zip a, b
      aElem = pair[0]
      bElem = pair[1]

      if not aElem?
        return -1
      if not bElem?
        return 1

      if aElem is bElem
        continue

      if _.isNumber aElem and not _.isNumber bElem
        return 1
      else if _.isNumber bElem and not _.isNumber aElem
        return -1

      if aElem > bElem
        return 1
      else
        return -1

    return 0

  parseFn = (fn) ->
    fn = fn.slice(0, -8)
    parts = fn.split('-')
    build = parts[parts.length - 1]
    return {
      build: build
      version: parts[parts.length - 2]
      name: parts.slice(0, -2).join('-')
      buildno: parseInt(build.split('_')[1], 10)
      pyver: parseInt(build.split('_')[0].slice(2), 10)
      }

  # Models and Collections

  class Model extends Backbone.Model
    constructor: (condaObject, options={}) ->
      super condaObject, options
      @conda = condaObject

  class Environment extends Model
    removeEnv: (options={}) ->
      promise = @conda.removeEnv options
      promise.then =>
        @destroy()
      return promise

  class Package extends Model
    # A Package installed in an environment.

    isApp: ->

  class Environments extends Backbone.Collection
    model: Environment
    sync: context.Env.backboneSync
    comparator: naturalSortComparator

  class Linked extends Backbone.Collection
    model: Package

    initialize: (models, options) ->
      @env = options.env

    sync: (method, model, options) ->
      @env.conda.linked().then (linked) =>
        options.sucess linked.map(Package)

  class Index extends Backbone.Collection
    # Cannot add/remove from this collection
    model: Package

    sync: (method, model, options) ->
      switch method
        when "read"
          context.index().then (index) ->
            models = []
            for name, infos of index
              for info in infos
                pkg = new context.Package info.fn, info
                model = new Package pkg
                models.push model
            options.success models

  return {
    Environment: Environment,
    Environments: Environments
  }
