#!/usr/bin/env python
# -*- coding: utf-8 -*-

###############################################################################
#  Copyright Kitware Inc.
#
#  Licensed 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 cherrypy

from girder.api import access
from girder.api.v1.item import Item
from girder.api.describe import Description
from girder.api.rest import loadmodel, RestException
from girder.models.model_base import AccessType

from .tilesource import TestTileSource, TiffGirderTileSource, TileSourceException


class TilesItemResource(Item):

    def __init__(self, apiRoot):
        self.resourceName = 'item'
        apiRoot.item.route('GET', (':itemId', 'tiles'), self.getTilesInfo)
        apiRoot.item.route('POST', (':itemId', 'tiles'), self.createTiles)
        apiRoot.item.route('GET', (':itemId', 'tiles', 'zxy', ':z', ':x', ':y'),
                           self.getTile)

    def _loadTileSource(self, itemId):
        try:
            if itemId == 'test':
                tileSource = TestTileSource(256)
            else:
                item = self.model('item').load(id=itemId, level=AccessType.READ,
                                               user=self.getCurrentUser(), exc=True)
                tileSource = TiffGirderTileSource(item)
            return tileSource
        except TileSourceException as e:
            # TODO: sometimes this could be 400
            raise RestException(e.message, code=500)

    @access.public
    def getTilesInfo(self, itemId, params):
        tileSource = self._loadTileSource(itemId)
        return tileSource.getMetadata()

    getTilesInfo.description = (
        Description('Get multiresolution tiles metadata.')
        .param('itemId', 'The ID of the item, or "test".', paramType='path')
        .errorResponse('ID was invalid.')
        .errorResponse('Read access was denied for the item.', 403)
    )

    @access.user
    @loadmodel(model='item', map={'itemId': 'item'}, level=AccessType.WRITE)
    def createTiles(self, item, params):
        largeImageFileId = params.get('fileId')
        if not largeImageFileId:
            raise RestException('Missing "fileId" parameter.')
        if largeImageFileId not in ('test', 'clear'):
            largeImageFile = self.model('file').load(largeImageFileId,
                                                     force=True, exc=True)
            if largeImageFile['itemId'] != item['_id']:
                raise RestException('"fileId" must be a file on the same item as "itemId".')

            item['largeImage'] = largeImageFile['_id']
        elif largeImageFileId == 'clear':
            if 'largeImage' in item:
                del item['largeImage']
        else:
            item['largeImage'] = largeImageFileId
        self.model('item').save(item)

        # TODO: a better response
        return {
            'created': True
        }

    createTiles.description = (
        Description('Create a multiresolution image for this item.')
        .param('itemId', 'The ID of the item..', paramType='path')
        .param('fileId', 'The ID of the source file containing the image.')
    )

    @access.public
    def getTile(self, itemId, z, x, y, params):
        try:
            x, y, z = int(x), int(y), int(z)
        except ValueError:
            raise RestException('x, y, and z must be integers', code=400)

        tileSource = self._loadTileSource(itemId)
        try:
            tileData = tileSource.getTile(x, y, z)
        except TileSourceException as e:
            raise RestException(e.message, code=404)

        cherrypy.response.headers['Content-Type'] = 'image/jpeg'
        return lambda: tileData

    getTile.cookieAuth = True
    getTile.description = (
        Description('Get an image tile.')
        .param('itemId', 'The ID of the item, "test", or "clear".',
               paramType='path')
        .param('z', 'The layer number of the tile (0 is the most zoomed-out layer).', paramType='path')
        .param('x', 'The X coordinate of the tile (0 is the left side).', paramType='path')
        .param('y', 'The Y coordinate of the tile (0 is the top).', paramType='path')
        .errorResponse('ID was invalid.')
        .errorResponse('Read access was denied for the item.', 403)
    )

@@ -1345,16 +1345,93 @@
 eTiles)%0A
+        apiRoot.item.route('DELETE', (':itemId', 'tiles'), self.deleteTiles)%0A
         
@@ -1503,16 +1503,16 @@
  ':y'),%0A
-
         
@@ -2382,17 +2382,16 @@
 the item
-,
  or %22tes
@@ -2842,32 +2842,17 @@
 eId 
-not in ('test', 'clear')
+!= 'test'
 :%0A  
@@ -3657,17 +3657,16 @@
 he item.
-.
 ', param
@@ -3750,17 +3750,609 @@
 he image
-.
+ or '%0A               '%22test%22.')%0A    )%0A%0A    @access.user%0A    @loadmodel(model='item', map=%7B'itemId': 'item'%7D, level=AccessType.WRITE)%0A    def deleteTiles(self, item, params):%0A        deleted = False%0A        if 'largeImage' in item:%0A            del item%5B'largeImage'%5D%0A            self.model('item').save(item)%0A            deleted = True%0A        # TODO: a better response%0A        return %7B%0A            'deleted': deleted%0A        %7D%0A%0A    deleteTiles.description = (%0A        Description('Remove a multiresolution image from this item.')%0A        .param('itemId', 'The ID of the item.', paramType='path
 ')%0A    )
@@ -5035,46 +5035,21 @@
 item
-, %22test%22, or %22clear%22.',%0A              
+ or %22test%22.',
  par

Move the 'clear' functionality to a DELETE end point.