# Metadata about a file or directory in a user's Dropbox.
class Dropbox.File.Stat
  # Creates a Stat instance from a raw "metadata" response.
  #
  # @param {Object} metadata the result of parsing JSON API responses that are
  #   called "metadata" in the REST API documentation
  # @return {Dropbox.File.Stat} an instance wrapping the given API response
  @parse: (metadata) ->
    # NOTE: if the argument is not an object, it is returned; this makes the
    #       client code more compact
    if metadata and typeof metadata is 'object'
      new Dropbox.File.Stat metadata
    else
      metadata

  # @property {String} the path of this file or folder, relative to the user's
  #   Dropbox or to the application's folder
  path: null

  # @property {String} the name of this file or folder
  name: null

  # @property {Boolean} if true, the file or folder's path is relative to the
  #   application's folder; otherwise, the path is relative to the user's
  #   Dropbox
  inAppFolder: null

  # @property {Boolean} if true, this Stat instance describes a folder
  isFolder: null

  # @property {Boolean} if true, this Stat instance describes a file
  isFile: null

  # @property {Boolean} if true, the file or folder described by this Stat
  #   instance was from the user's Dropbox, and was obtained by an API call
  #   that returns deleted items
  isRemoved: null

  # @property {String} name of an icon in Dropbox's icon library that most
  #   accurately represents this file or folder
  #
  # See the {https://www.dropbox.com/developers/reference/api#metadata
  # Dropbox REST API documentation} to obtain the Dropbox icon library.
  typeIcon: null

  # @property {String} an identifier for the contents of the described file or
  #   directories; this can used to restore a file's contents to a
  #   previous version, or to save bandwidth by not retrieving the same
  #   folder contents twice
  versionTag: null

  # @property {String} a hash over the folder's contents; this can be used to
  #   save bandwidth when repeatedly reading a directory's content
  #
  # @see Dropbox.Client#stat
  # @see Dropbox.Client#readdir
  contentHash: null

  # @property {String} a guess of the MIME type representing the file or
  #   folder's contents
  mimeType: null

  # @property {Number} the size of the file, in bytes; null for folders
  size: null

  # @property {String} the size of the file, in a human-readable format, such
  #   as "225.4KB"; the format of this string is influenced by the API client's
  #   locale
  humanSize: null

  # @property {Boolean} if false, the URL generated by thumbnailUrl does not
  #   point to a valid image, and should not be used
  hasThumbnail: null

  # @property {Date} the file or folder's last modification time
  modifiedAt: null

  # @property {Date} the file or folder's last modification time, as reported
  #   by the Dropbox client that uploaded the file; this time should not be
  #   trusted, but can be used for UI (display, sorting); this is null if the
  #   server does not report any time
  clientModifiedAt: null

  # JSON representation of this file / folder's metadata
  #
  # @return {Object} an object that can be serialized using JSON; the object
  #   can be passed to {Dropbox.File.Stat.parse} to obtain a Stat instance with
  #   the same information
  toJSON: ->
    @_json

  # @deprecated
  # @see Dropbox.File.Stat#toJSON
  json: ->
    @toJSON()

  # Creates a Stat instance from a raw "metadata" response.
  #
  # @private
  # This constructor is used by {Dropbox.File.Stat.parse}, and should not be
  # called directly.
  #
  # @param {Object} metadata the result of parsing JSON API responses that are
  #   called "metadata" in the API documentation
  constructor: (metadata) ->
    @_json = metadata
    @path = metadata.path
    # Ensure there is a trailing /, to make path processing reliable.
    @path = '/' + @path if @path.substring(0, 1) isnt '/'
    # Strip any trailing /, to make path joining predictable.
    lastIndex = @path.length - 1
    if lastIndex >= 0 and @path.substring(lastIndex) is '/'
      @path = @path.substring 0, lastIndex

    nameSlash = @path.lastIndexOf '/'
    @name = @path.substring nameSlash + 1

    @isFolder = metadata.is_dir || false
    @isFile = !@isFolder
    @isRemoved = metadata.is_deleted || false
    @typeIcon = metadata.icon
    if metadata.modified?.length
      @modifiedAt = Dropbox.Util.parseDate metadata.modified
    else
      @modifiedAt = null
    if metadata.client_mtime?.length
      @clientModifiedAt = Dropbox.Util.parseDate metadata.client_mtime
    else
      @clientModifiedAt = null

    switch metadata.root
      when 'dropbox'
        @inAppFolder = false
      when 'app_folder'
        @inAppFolder = true
      else
        # New "root" value that we're not aware of.
        @inAppFolder = null

    @size = metadata.bytes or 0
    @humanSize = metadata.size or ''
    @hasThumbnail = metadata.thumb_exists or false
    @versionTag = metadata.rev
    @contentHash = metadata.hash or null

    if @isFolder
      @mimeType = metadata.mime_type || 'inode/directory'
    else
      @mimeType = metadata.mime_type || 'application/octet-stream'
