# -*- coding: utf-8 -*-

'''
Read content from ztxt pdb file.
'''

__license__   = 'GPL v3'
__copyright__ = '2009, John Schember <john@nachtimwald.com>'
__docformat__ = 'restructuredtext en'

import os, struct, zlib

from calibre.ebooks.pdb.formatreader import FormatReader
from calibre.ebooks.pdb.ztxt import zTXTError
from calibre.ebooks.txt.processor import convert_basic, opf_writer, \
    separate_paragraphs_single_line, separate_paragraphs_print_formatted

SUPPORTED_VERSION = (1, 40)

class HeaderRecord(object):
    '''
    The first record in the file is always the header record. It holds
    information related to the location of text, images, and so on
    in the file. This is used in conjunction with the sections
    defined in the file header.
    '''

    def __init__(self, raw):
        self.version, = struct.unpack('>H', raw[0:2])
        self.num_records, = struct.unpack('>H', raw[2:4])
        self.size, = struct.unpack('>L', raw[4:8])
        self.record_size, = struct.unpack('>H', raw[8:10])
        self.flags, = struct.unpack('>B', raw[18:19])


class Reader(FormatReader):

    def __init__(self, header, stream, log, options):
        self.stream = stream
        self.log = log
        self.encoding = options.input_encoding
        self.single_line_paras = options.single_line_paras
        self.print_formatted_paras = options.print_formatted_paras

        self.sections = []
        for i in range(header.num_sections):
            self.sections.append(header.section_data(i))

        self.header_record = HeaderRecord(self.section_data(0))

        vmajor = (self.header_record.version & 0x0000FF00) >> 8
        vminor = self.header_record.version & 0x000000FF
        if vmajor < 1 or (vmajor == 1 and vminor < 40):
            raise zTXTError('Unsupported ztxt version (%i.%i). Only versions newer than %i.%i are supported.' % (vmajor, vminor, SUPPORTED_VERSION[0], SUPPORTED_VERSION[1]))

        if (self.header_record.flags & 0x01) == 0:
            raise zTXTError('Only compression method 1 (random access) is supported')

        self.log.debug('Foud ztxt version: %i.%i' % (vmajor, vminor))

        # Initalize the decompressor
        self.uncompressor = zlib.decompressobj()
        self.uncompressor.decompress(self.section_data(1))

    def section_data(self, number):
        return self.sections[number]

    def decompress_text(self, number):
        if number == 1:
            self.uncompressor = zlib.decompressobj()
        return self.uncompressor.decompress(self.section_data(number)).decode('cp1252' if self.encoding is None else self.encoding, 'replace')

    def extract_content(self, output_dir):
        txt = ''

        self.log.info('Decompressing text...')
        for i in range(1, self.header_record.num_records + 1):
            self.log.debug('\tDecompressing text section %i' % i)
            txt += self.decompress_text(i)

        self.log.info('Converting text to OEB...')
        if self.single_line_paras:
            txt = separate_paragraphs_single_line(txt)
        if self.print_formatted_paras:
            txt = separate_paragraphs_print_formatted(txt)
        html = convert_basic(txt)
        with open(os.path.join(output_dir, 'index.html'), 'wb') as index:
            index.write(html.encode('utf-8'))

        from calibre.ebooks.metadata.meta import get_metadata
        mi = get_metadata(self.stream, 'pdb')
        manifest = [('index.html', None)]
        spine = ['index.html']
        opf_writer(output_dir, 'metadata.opf', manifest, spine, mi)

        return os.path.join(output_dir, 'metadata.opf')

