#       Licensed to the Apache Software Foundation (ASF) under one
#       or more contributor license agreements.  See the NOTICE file
#       distributed with this work for additional information
#       regarding copyright ownership.  The ASF licenses this file
#       to you under 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
#
#       Unless required by applicable law or agreed to in writing,
#       software distributed under the License is distributed on an
#       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
#       KIND, either express or implied.  See the License for the
#       specific language governing permissions and limitations
#       under the License.

import sys

import PIL
from pylons import tmpl_context as c

from ming.orm import ThreadLocalORMSession, state, Mapper

from allura.command import base
from allura.lib.helpers import iter_entry_points


class RethumbCommand(base.Command):
    min_args = 1
    max_args = 2
    usage = '<ini file> [<project name>]'
    summary = 'Recreate thumbnails for attachment images'
    parser = base.Command.standard_parser(verbose=True)
    parser.add_option('', '--force', dest='force', action='store_true',
                      help=('Recreate all thumbnails (by first removing any existing)'))

    created_thumbs = 0

    def create_thumbnail(self, attachment, att_cls):
        if attachment.is_image():
            base.log.info("Processing image attachment '%s'",
                          attachment.filename)
            doc = state(attachment).document.deinstrumented_clone()
            del doc['_id']
            del doc['file_id']
            doc['type'] = 'thumbnail'
            count = att_cls.query.find(doc).count()
            if count == 1:
                base.log.info(
                    "Thumbnail already exists for '%s' - skipping", attachment.filename)
                return
            elif count > 1:
                base.log.warning(
                    "There are %d thumbnails for '%s' - consider clearing them with --force", count, attachment.filename)
                return

            image = PIL.Image.open(attachment.rfile())
            del doc['content_type']
            del doc['filename']
            att_cls.save_thumbnail(attachment.filename, image,
                                   attachment.content_type, att_cls.thumbnail_size, doc, square=True)
            base.log.info("Created thumbnail for '%s'", attachment.filename)
            self.created_thumbs += 1

    def process_att_of_type(self, cls, find_criteria):
        base.log.info('Processing attachment class: %s', cls)
        find_criteria['type'] = 'attachment'
        for att in cls.query.find(find_criteria):
            self.create_thumbnail(att, cls)

    def command(self):
        from allura import model as M
#        self.basic_setup()

        existing_thumbs = 0
        base.log.info('Collecting application attachment classes')
        package_model_map = {}
        for m in Mapper.all_mappers():
            sess = m.session
            cls = m.mapped_class
            if issubclass(cls, M.BaseAttachment):
                if sess is M.project_orm_session:
                    package = cls.__module__.split('.', 1)[0]
                    l = package_model_map.get(package, [])
                    l.append(cls)
                    package_model_map[package] = l

        if len(self.args) > 1:
            projects = M.Project.query.find({'shortname': self.args[1]})
        else:
            projects = M.Project.query.find()
        for p in projects:
            base.log.info('=' * 20)
            base.log.info("Processing project '%s'", p.shortname)
            c.project = p

            if self.options.force:
                existing_thumbs += M.BaseAttachment.query.find({'type': 'thumbnail'}
                                                               ).count()
                base.log.info(
                    'Removing %d current thumbnails (per --force)', existing_thumbs)
                M.BaseAttachment.query.remove({'type': 'thumbnail'})

            # ProjectFile's live in main collection (unlike File's)
            # M.ProjectFile.query.find({'app_config_id': None, 'type': 'attachment'}).all()

            for app in p.app_configs:
                base.log.info(
                    "Processing application '%s' mounted at '%s' of type '%s'",
                    app.options['mount_label'], app.options['mount_point'], app.tool_name)

                # Any application may contain DiscussionAttachment's, it has
                # discussion_id field
                self.process_att_of_type(
                    M.DiscussionAttachment, {'app_config_id': app._id, 'discussion_id': {'$ne': None}})

                # Otherwise, we'll take attachment classes belonging to app's
                # package
                ep = iter_entry_points('allura', app.tool_name).next()
                app_package = ep.module_name.split('.', 1)[0]
                if app_package == 'allura':
                    # Apps in allura known to not define own attachment types
                    continue

                classes = package_model_map.get(app_package, [])
                for cls in classes:
                    self.process_att_of_type(
                        cls, {'app_config_id': app._id, 'discussion_id': None})

                base.log.info('-' * 10)

        base.log.info('Recreated %d thumbs', self.created_thumbs)
        if self.options.force:
            if existing_thumbs != self.created_thumbs:
                base.log.warning(
                    'There were %d thumbs before --force operation started, but %d recreated',
                    existing_thumbs, self.created_thumbs)

        ThreadLocalORMSession.flush_all()


if __name__ == '__main__':
    command = RethumbCommand('rethumb')
    command.parse_args(sys.argv)
    command.command()
