## Copyright (c) 2007 Ashish Kulkarni
##
## Permission is hereby granted, free of charge, to any person obtaining a
## copy of this software and associated documentation files (the "Software"),
## to deal in the Software without restriction, including without limitation
## the rights to use, copy, modify, merge, publish, distribute, sublicense,
## and/or sell copies of the Software, and to permit persons to whom the
## Software is furnished to do so, subject to the following conditions:
##
## The above copyright notice and this permission notice shall be included in
## all copies or substantial portions of the Software.
##
## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
## IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
## AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
## FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
## DEALINGS IN THE SOFTWARE.


import os, sys, traceback

from common import *
from PIL import Image

VERSION               = 'PDFRead v1.8.2b'
TINY_MARGIN           = '2px'
NO_MARGIN             = '0em'

EXTENT                = 1
MAXHEIGHT_SONY        = 754
WHITE                 = 255

########################################################## HTML OUTPUT


""" support for HTML output """
class HtmlOutput(BaseOutput):
  __plugin__ = 'html'

  """ generate an HTML table-of-contents """
  def toc_text(self, toc):
    current  = 0
    toc_text = ''
    toc_map  = self.toc_map

    for title_, level_, page_ in toc:
      title, level, page = title_.strip(), int(level_), int(page_)

      if not toc_map.has_key(page):
        continue

      if level > current:
        current = level
        toc_text += '<ul>'
      elif current > level:
        current = level
        toc_text += '</ul>'
      
      #KLUDGE:  removed trailing </li> to fix (broken) layout problems
      toc_text += '<li><a href="#img%d">%s</a>' % (toc_map[page], title)

    while current > 0:
      toc_text += '</ul>'
      current  = current - 1

    return toc_text

  """ generate an HTML file """
  def generate(self, toc):
    return self.generate_html(toc, 0)


  """ generate an HTML file """
  def generate_html(self, toc, device):
    output = """
<html>
 <head>
  <title>%(title)s</title>
  <meta name="author"    content="%(author)s">
  <meta name="genre"     content="%(category)s">
  <meta name="category"  content="%(category)s">
  <meta name="generator" content="%(ver)s">
  <style>p {text-indent:0em; margin-left:%(margin)s; margin-right:%(margin)s; margin-top:0em; margin-bottom:0em; text-align:%(rotate)s}</style>
 </head>
 <body>
  <h2 align="center">%(title)s</h2>
  <h2 align="center">by</h2>
  <h2 align="center">%(author)s</h2>
  %(toc)s""" % dict(title=self.title, author=self.author, category=self.category, ver=VERSION,
                    margin=TINY_MARGIN if device==1 else NO_MARGIN, rotate=self.rotate, toc=self.toc_text(toc))
    output += '\n  <p style="page-break-before: always">\n'
    if device < 0:
      output += '  <mbp:pagebreak />\n'
    for i in range(self.n):
      name = IMAGENAME_SPEC % i
      output += '  <p><a name="img%d"></a><img src="%s"/></p>\n' % (i, name)
    output += ' </body>\n</html>'
    write_file(self.outname+'.html', output)

    return False


############################################################ RB OUTPUT


""" support for Rocket ebook (RB) output """
class RocketBookOutput(HtmlOutput):
  __plugin__ = 'rb'

  """ generate a rocket ebook """
  def generate(self, toc):

    HtmlOutput.generate_html(self, toc, 3)

    if COMMANDS['rbmake']:
      p('\nCreating Rocket ebook ... ')
      call('rbmake', '-bei', '-Enone', '-o', self.outname+'.rb', self.outname+'.html')
      p('done.\n')

    return self.move_output('rb')


########################################################### IMP OUTPUT


""" support for IMP output """
class ImpOutput(HtmlOutput):

  """ generate a IMP for the specified device """
  def generate_imp(self, toc, device):

    HtmlOutput.generate_html(self, toc, device)

    if sys.platform != 'win32':
      p('IMP creation disabled (works only on Windows).\n')
      return False

    p('\nCreating file ... ')
    try:
      from win32com.client import Dispatch
      from win32com.client import gencache

      gencache.is_readonly = False
      gencache.EnsureModule('{1103EA00-3A0C-11D3-A6F6-00104B2947FB}', 0, 1, 0)

      builder = Dispatch('SBPublisher.Builder')
      project = Dispatch('SBPublisher.Project')

      project.AuthorFirstName = self.author
      project.BookTitle       = self.title
      project.Category        = self.category

      project.BookFileName    = self.outname
      project.OutputDirectory = '.'
      project.BuildTarget     = device
      project.Compress        = True
      project.Encrypt         = False
      project.KeepAnchors     = True
      project.Language        = 'en'
      project.RequireISBN     = False
      project.Zoom            = 2

      project.AddSourceFile(self.outname+'.html')
      project.Save(self.outname+'.opf')
      if device:
        builder.Build(project)
      else:
	builder.GenerateOEBFF(project, 1)
        p('done .oeb build.\n')
        return self.move_output('oeb')

      p('done .imp build.\n')

    except:
      print 'failed, error details follow.\n'
      traceback.print_exc(file=sys.stdout)

    return self.move_output('imp')


""" support for OEBFF output for the .oeb profile """
class OEBFFImpOutput(ImpOutput):
  __plugin__ = 'oeb'

  def generate(self, toc):
    return self.generate_imp(toc, 0)

""" support for IMP output for the FullVga profile """
class FullVgaImpOutput(ImpOutput):
  __plugin__ = 'imp1'

  def generate(self, toc):
    return self.generate_imp(toc, 1)

""" support for IMP output for the HalfVga profile """
class HalfVgaImpOutput(ImpOutput):
  __plugin__ = 'imp2'

  def generate(self, toc):
    return self.generate_imp(toc, 2)


############################################################ PRC OUTPUT


""" support for Mobipocket PRC output """
class MobipocketOutput(ImpOutput):
  __plugin__ = 'prc'

  """ generate a mobipocket ebook """
  def generate(self, toc):
    HtmlOutput.generate_html(self, toc, -1)

    if COMMANDS['NRhtml2mobi']:
      p('\nCreating Mobipocket ebook ... ')
      call('NRhtml2mobi', self.outname+'.html', '--title', self.title,  '--author', self.author, '--mobifile', self.outname+'.prc')
      p('done.\n')

    return self.move_output('prc')


########################################################## BBEB OUTPUT


""" support for Sony BBeB output """
class LrfOutput(BaseOutput):
  __plugin__ = 'lrf'

  """ generate a LRF file """
  def generate(self, toc):
    from pylrs.pylrs import Book, PageStyle, BlockStyle
    from pylrs.pylrs import ImageStream, BlockSpace, ImageBlock

    p('\nCreating file ... ')

    # create book instance
    book = Book(title=self.title, author=self.author, category=self.category)

    # create default styles
    pageStyle  = PageStyle(topmargin='0', oddsidemargin='0', evensidemargin='0')
    blockStyle = BlockStyle(blockwidth='600', blockheight='800')

    # create pages
    images = []
    for i in range(self.n):
      imagefile = IMAGENAME_SPEC % i
      im = Image.open(imagefile)
      imformat, imsize = im.format, im.size
      imwidth, imheight = imsize
      if (imheight < MAXHEIGHT_SONY):
          newsize = imwidth, MAXHEIGHT_SONY
          im = im.transform(newsize, EXTENT, (0, 0, imwidth, MAXHEIGHT_SONY))
          im.paste(WHITE, (0, imheight, imwidth, MAXHEIGHT_SONY))
          im.format = imformat
          im.save(imagefile, imformat)
      
      stream = ImageStream(imagefile)
      page   = book.Page(pageStyle)
      page.BlockSpace()
      image  = page.ImageBlock(refstream=stream, xsize='584', ysize='754',
                               blockheight='768', blockStyle=blockStyle)
      images.append(image)

    # generate TOC, if present
    toc_map = self.toc_map
    for title, level, page_ in toc:
      if toc_map.has_key(int(page_)):
        imagenum = toc_map[int(page_)]
        book.addTocEntry(title.strip(), images[imagenum])

    # generate the ebook
    book.renderLrf(self.outname+".lrf")

    p('done BBeB build.\n')

    return self.move_output('lrf')

