from Persistent import Persistent, quote


class File( Persistent ):
  """
  Metadata about an uploaded file. The actual file data is stored on the filesystem instead of in
  the database. (Binary conversion to/from PostgreSQL's bytea is too slow, and the version of
  psycopg2 I'm using doesn't have large object support.)
  """
  def __init__( self, object_id, revision = None, notebook_id = None, note_id = None,
                filename = None, size_bytes = None, content_type = None ):
    """
    Create a File with the given id.

    @type object_id: unicode
    @param object_id: id of the File
    @type revision: datetime or NoneType
    @param revision: revision timestamp of the object (optional, defaults to now)
    @type notebook_id: unicode or NoneType
    @param notebook_id: id of the notebook containing the file
    @type note_id: unicode or NoneType
    @param note_id: id of the note linking to the file
    @type filename: unicode
    @param filename: name of the file on the client
    @type size_bytes: int
    @param size_bytes: length of the file data in bytes
    @type content_type: unicode
    @param content_type: value of the Content-Type HTTP header for this file
    @rtype: File
    @return: newly constructed File
    """
    Persistent.__init__( self, object_id, revision )
    self.__notebook_id = notebook_id
    self.__note_id = note_id
    self.__filename = filename
    self.__size_bytes = size_bytes
    self.__content_type = content_type

  @staticmethod
  def create( object_id, notebook_id = None, note_id = None, filename = None, size_bytes = None, content_type = None ):
    """
    Convenience constructor for creating a new File.

    @type object_id: unicode
    @param object_id: id of the File
    @type notebook_id: unicode or NoneType
    @param notebook_id: id of the notebook containing the file
    @type note_id: unicode or NoneType
    @param note_id: id of the note linking to the file
    @type filename: unicode
    @param filename: name of the file on the client
    @type size_bytes: int
    @param size_bytes: length of the file data in bytes
    @type content_type: unicode
    @param content_type: value of the Content-Type HTTP header for this file
    @rtype: File
    @return: newly constructed File
    """
    return File( object_id, notebook_id = notebook_id, note_id = note_id, filename = filename,
                 size_bytes = size_bytes, content_type = content_type )

  @staticmethod
  def sql_load( object_id, revision = None ):
    # Files don't store old revisions
    if revision:
      raise NotImplementedError()

    return \
      """
      select
        file.id, file.revision, file.notebook_id, file.note_id, file.filename, file.size_bytes, file.content_type
      from
        file
      where
        file.id = %s;
      """ % quote( object_id )

  @staticmethod
  def sql_id_exists( object_id, revision = None ):
    if revision:
      raise NotImplementedError()

    return "select id from file where id = %s;" % quote( object_id )

  def sql_exists( self ):
    return File.sql_id_exists( self.object_id )

  def sql_create( self ):
    return "insert into file ( id, revision, notebook_id, note_id, filename, size_bytes, content_type ) values ( %s, %s, %s, %s, %s, %s, %s );" % \
    ( quote( self.object_id ), quote( self.revision ), quote( self.__notebook_id ), quote( self.__note_id ),
      quote( self.__filename ), self.__size_bytes or 'null', quote( self.__content_type ) )

  def sql_update( self ):
    return "update file set revision = %s, notebook_id = %s, note_id = %s, filename = %s, size_bytes = %s, content_type = %s where id = %s;" % \
    ( quote( self.revision ), quote( self.__notebook_id ), quote( self.__note_id ), quote( self.__filename ),
      self.__size_bytes or 'null', quote( self.__content_type ), quote( self.object_id ) )

  def sql_delete( self ):
    return "delete from file where id = %s;" % quote( self.object_id )

  @staticmethod
  def sql_load_note_files( note_id ):
    return \
      """
      select
        file.id, file.revision, file.notebook_id, file.note_id, file.filename, file.size_bytes, file.content_type
      from
        file
      where
        file.note_id = %s;
      """ % quote( note_id )

  def to_dict( self ):
    d = Persistent.to_dict( self )
    d.update( dict(
      notebook_id = self.__notebook_id,
      note_id = self.__note_id,
      filename = self.__filename,
      size_bytes = self.__size_bytes,
      content_type = self.__content_type,
    ) )

    return d

  def __set_filename( self, filename ):
    self.__filename = filename

  notebook_id = property( lambda self: self.__notebook_id )
  note_id = property( lambda self: self.__note_id )
  filename = property( lambda self: self.__filename, __set_filename )
  size_bytes = property( lambda self: self.__size_bytes )
  content_type = property( lambda self: self.__content_type )
