#!/usr/bin/env python
# -*- coding: UTF-8 -*-
#
# Copyright (c) 2009-2010 Ars Aperta, Itaapy, Pierlis, Talend.
#
# Authors: Hervé Cauwelier <herve@itaapy.com>
#          Romain Gauthier <romain@itaapy.com>
#
# This file is part of Lpod (see: http://lpod-project.net).
# Lpod is free software; you can redistribute it and/or modify it under
# the terms of either:
#
# a) the GNU General Public License as published by the Free Software
#    Foundation, either version 3 of the License, or (at your option)
#    any later version.
#    Lpod is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#    You should have received a copy of the GNU General Public License
#    along with Lpod.  If not, see <http://www.gnu.org/licenses/>.
#
# b) the Apache License, Version 2.0 (the "License");
#    you may not use this file except in compliance with the License.
#    You may obtain a copy of the License at
#    http://www.apache.org/licenses/LICENSE-2.0
#
 
# Import from the standard library
from optparse import OptionParser
from sys import exit, stdout
 
# Import from lpod
from lpod import __version__
from lpod.const import ODF_CLASSES
from lpod.document import odf_get_document
from lpod.scriptutils import add_option_output, StdoutWriter, printinfo
from lpod.scriptutils import check_target_file, printerr
 
 
def show_styles(document, target, automatic=True, common=True,
        properties=False):
    """Show the different styles of a document and their properties.
    """
    output = document.show_styles(automatic=automatic, common=common,
            properties=properties)
    # Print the output
    if target is None:
        target = stdout
    encoding = target.encoding if target.encoding is not None else 'utf-8'
    target.write(output.encode(encoding))
    target.flush()
 
 
 
def delete_styles(document, target, pretty=True):
    n = document.delete_styles()
    document.save(target=target, pretty=pretty)
    printinfo(str(n), "styles removed (0 error, 0 warning).")
 
 
 
def find_presentation_list_style(body):
    for frame in body.get_frames(presentation_class='outline'):
        first_list = frame.get_list()
        if first_list is not None:
            return first_list.get_style()
    return None
 
 
 
def merge_presentation_styles(document, source):
    # Apply master page found
    source_body = source.get_body()
    first_page = source_body.get_draw_page()
    master_page_name = first_page.get_master_page()
    first_master_page = document.get_style('master-page',
            master_page_name)
    printinfo("master page used:", first_master_page.get_display_name())
    body = document.get_body()
    for page in body.get_draw_pages():
        page.set_style(first_page.get_style())
        page.set_master_page(first_page.get_master_page())
        page.set_presentation_page_layout(
                first_page.get_presentation_page_layout())
    # Adjust layout -- will obviously work only if content is separated from
    # style: use of master pages, layout, etc.
    for presentation_class in ODF_CLASSES:
        first_frame = source_body.get_frame(
                presentation_class=presentation_class)
        if first_frame is None:
            continue
        # Mimic frame style
        position = first_frame.get_position()
        size = first_frame.get_size()
        style = first_frame.get_style()
        presentation_style = first_frame.get_presentation_style()
        for page in body.get_draw_pages():
            for frame in page.get_frames(
                    presentation_class=presentation_class):
                frame.set_position(position)
                frame.set_size(size)
                frame.set_style(style)
                frame.set_presentation_style(presentation_style)
        # Mimic list style (XXX only first level)
        if presentation_class == 'outline':
            list_style = find_presentation_list_style(source_body)
            for page in body.get_draw_pages():
                for frame in page.get_frames(
                        presentation_class='outline'):
                    for list in frame.get_lists():
                        list.set_style(list_style)
 
 
 
def merge_styles(document, from_file, target=None, pretty=True):
    source = odf_get_document(from_file)
    document.delete_styles()
    document.merge_styles_from(source)
    type = document.get_type()
    # Enhance Presentation merge
    if type in ('presentation', 'presentation-template'):
        printinfo("merging presentation styles...")
        merge_presentation_styles(document, source)
    document.save(target=target, pretty=pretty)
    printinfo("Done (0 error, 0 warning).")
 
 
 
if  __name__ == '__main__':
    # Options initialisation
    usage = '%prog [options] <file>'
    description = ("A command line interface to manipulate styles of "
            "OpenDocument files. By default prints all the styles to the "
            "standard output.")
    parser = OptionParser(usage, version=__version__,
            description=description)
    # --automatic
    parser.add_option('-a', '--automatic', action='store_true', default=False,
            help="show automatic styles only")
    # --common
    parser.add_option('-c', '--common', action='store_true', default=False,
            help="show common styles only")
    # --properties
    parser.add_option('-p', '--properties', action='store_true',
            help="show properties of styles")
    # --delete
    help = ("return a copy with all styles (except default) deleted from "
            "<file>")
    parser.add_option('-d', '--delete', action='store_true', help=help)
    # --merge
    help = ('copy styles from FILE to <file>. Any style with the same name '
            'will be replaced.')
    parser.add_option('-m', '--merge-styles-from', dest='merge',
            metavar='FILE', help=help)
    # --output
    add_option_output(parser)
    # Parse options
    options, args = parser.parse_args()
    if len(args) != 1:
        parser.print_help()
        exit(1)
    document = odf_get_document(args[0])
    if options.delete:
        target = options.output
        if target is None:
            printerr("Will not delete in-place: ",
                    'output file needed or "-" for stdout')
            exit(1)
        elif target == "-":
            target = StdoutWriter()
        else:
            check_target_file(target)
        delete_styles(document, target)
    elif options.merge:
        merge_styles(document, options.merge, target=options.output)
    else:
        automatic = options.automatic
        common = options.common
        if not automatic ^ common:
            automatic, common = True, True
        target = options.output
        if target is not None:
            target = open(target, 'wb')
        show_styles(document, target, automatic=automatic,
                common=common, properties=options.properties)