#!/usr/bin/env python
# -*- coding: utf-8 -*-
# **************************************************************************
# Copyright © 2019 jianglin
# File Name: router.py
# Author: jianglin
# Email: mail@honmaple.com
# Created: 2017-03-12 19:54:12 (CST)
# Last Update: Monday 2019-01-07 15:17:42 (CST)
#          By:
# Description:
# **************************************************************************
from flask import request, current_app
from flask_maple.response import HTTP
from flask_maple.serializer import PageInfo
from flask_maple.views import IsAuthMethodView as MethodView
from datetime import datetime
from time import time
from random import randint
from threading import Thread
from PIL import Image as ImagePIL
from storage.serializer import (ImageSerializer, AlbumSerializer)
from storage.util import (gen_filter_dict, gen_order_by, gen_hash,
                          file_is_allowed)
from .model import Image, Album
import os


class AlbumListView(MethodView):
    def get(self):
        '''
        获取相册列表
        '''
        query_dict = request.data
        user = request.user
        page, number = self.page_info
        keys = ['name', 'description']
        order_by = gen_order_by(query_dict, keys)
        filter_dict = gen_filter_dict(query_dict, keys, user=user)
        albums = Album.query.filter_by(
            **filter_dict).order_by(*order_by).paginate(page, number)
        serializer = AlbumSerializer(albums.items, True)
        pageinfo = PageInfo(albums)
        return HTTP.OK(data=serializer.data, pageinfo=pageinfo)

    def post(self):
        '''
        新建相册
        '''
        post_data = request.data
        user = request.user
        name = post_data.pop('name', None)
        description = post_data.pop('description', None)
        if name is None:
            return HTTP.BAD_REQUEST(message='相册名称不能为空')
        album = Album(name=name, user=user)
        if description is not None:
            album.description = description
        album.save()
        serializer = AlbumSerializer(album)
        return HTTP.OK(data=serializer.data)


class AlbumView(MethodView):
    def get(self, pk):
        '''
        获取具体相册
        '''
        user = request.user
        album = Album.query.filter_by(id=pk, user=user).get_or_404('相册不存在')
        serializer = AlbumSerializer(album)
        return HTTP.OK(data=serializer.data)

    def put(self, pk):
        '''
        修改相册
        '''
        post_data = request.data
        user = request.user
        name = post_data.pop('name', None)
        description = post_data.pop('description', None)
        album = Album.query.filter_by(id=pk, user=user).get_or_404('相册不存在')
        if name is not None:
            album.name = name
        if description is not None:
            album.description = description
        album.save()
        serializer = AlbumSerializer(album)
        album.delete()
        return HTTP.OK(data=serializer.data)

    def delete(self, pk):
        '''
        删除具体相册
        '''
        user = request.user
        album = Album.query.filter_by(id=pk, user=user).get_or_404('相册不存在')
        serializer = AlbumSerializer(album)
        album.delete()
        return HTTP.OK(data=serializer.data)


class ImageListView(MethodView):
    def get(self):
        '''
        获取图片列表
        '''
        query_dict = request.data
        user = request.user
        page, number = self.page_info
        keys = ['name', 'description']
        order_by = gen_order_by(query_dict, keys)
        filter_dict = gen_filter_dict(query_dict, keys, user=user)
        album = query_dict.pop('album', None)
        if album is not None:
            filter_dict.update(album__id=album)
        images = Image.query.filter_by(
            **filter_dict).order_by(*order_by).paginate(page, number)
        serializer = ImageSerializer(images.items, True)
        pageinfo = PageInfo(images)
        return HTTP.OK(data=serializer.data, pageinfo=pageinfo)

    def post(self):
        '''
        上传图片
        '''
        user = request.user
        post_data = request.data
        album = post_data.pop('album', None)
        # 相册
        if album is not None:
            album = Album.query.filter_by(id=album, user=user).first()
        if not album:
            default_album = Album.query.filter_by(
                name='default', user=user).first()
            if not default_album:
                default_album = Album(name='default', user=user)
                default_album.save()
            album = default_album
        images = request.files.getlist('images')
        t = datetime.now()
        # 将会保存到数据库中的路径
        path = os.path.join(current_app.config['UPLOAD_FOLDER_PATH'],
                            user.username, 'photo', t.strftime('%Y'),
                            t.strftime('%m'))
        # 将会保存到磁盘中的路径
        base_path = os.path.join(current_app.config['UPLOAD_FOLDER_ROOT'],
                                 path)
        if not os.path.exists(base_path):
            os.makedirs(base_path)
        success_images = []
        fail_images = []
        for image in images:
            if not file_is_allowed(image.filename):
                msg = '{name} 不允许的扩展'.format(name=image.filename)
                return HTTP.BAD_REQUEST(message=msg)
            name = '{name}.png'.format(
                name=str(int(time() * 1000)) + str(randint(10, 99)))
            # 计算sha-512值,避免重复保存
            hash = gen_hash(image)
            if Image.query.filter_by(hash=hash, user=user).exists():
                success_images.append(image.filename)
                continue

            # 保存到磁盘中
            img_path = os.path.join(base_path, name)
            # http://stackoverflow.com/questions/42569942/calculate-md5-from-werkzeug-datastructures-filestorage-but-saving-the-object-as
            image.seek(0)
            image.save(img_path)
            # 保存到数据库中
            img = Image(
                name=name, path=path, hash=hash, user=user, album=album)
            img.url = os.path.join(path, name)
            img.save()
            serializer = ImageSerializer(img)
            success_images.append(serializer.data)
            # 缩略图路径
            thumb_path = os.path.join(current_app.config['UPLOAD_FOLDER_ROOT'],
                                      img_path.replace('photo', 'thumb'))
            # 展示图路径
            show_path = os.path.join(current_app.config['UPLOAD_FOLDER_ROOT'],
                                     img_path.replace('photo', 'show'))
            t = Thread(
                target=self.gen_thumb_image, args=(img_path, thumb_path, 300))
            t.setDaemon(True)
            t.start()
            t = Thread(
                target=self.gen_thumb_image, args=(img_path, show_path, 810))
            t.setDaemon(True)
            t.start()

        return HTTP.OK(data={'success': success_images, 'fail': fail_images})

    def gen_thumb_image(self, img_path, thumb_path, width):
        '''
        生成缩略图 or 展示图
        '''
        base_path = os.path.dirname(thumb_path)
        if not os.path.exists(base_path):
            os.makedirs(base_path)
        img = ImagePIL.open(img_path)
        if img.size[0] <= width:
            img.save(thumb_path, 'PNG')
            return thumb_path
        width = width
        height = float(width) / img.size[0] * img.size[1]
        img.thumbnail((width, height), ImagePIL.ANTIALIAS)
        img.save(thumb_path, 'PNG')
        return thumb_path


class ImageView(MethodView):
    def get(self, pk):
        '''
        显示图片
        '''
        user = request.user
        image = Image.query.filter_by(id=pk, user=user).get_or_404('图片不存在')
        serializer = ImageSerializer(image)
        return HTTP.OK(data=serializer.data)

    def put(self, pk):
        '''
        修改图片信息
        '''
        post_data = request.data
        user = request.user
        name = post_data.pop('name', None)
        description = post_data.pop('description', None)
        image = Image.query.filter_by(id=pk, user=user).get_or_404('图片不存在')
        if name is not None:
            image.name = name
            image.url = os.path.join(image.path, name)
        if description is not None:
            image.description = description
        image.save()
        serializer = ImageSerializer(image)
        return HTTP.OK(data=serializer.data)

    def delete(self, pk):
        '''
        删除图片
        '''
        user = request.user
        image = Image.query.filter_by(id=pk, user=user).get_or_404('图片不存在')
        serializer = ImageSerializer(image)
        img_path = os.path.join(current_app.config['UPLOAD_FOLDER_ROOT'],
                                image.url)
        # 删除原图
        if os.path.exists(img_path):
            os.remove(img_path)
        # 删除缩略图
        thumb_path = os.path.join(current_app.config['UPLOAD_FOLDER_ROOT'],
                                  image.url.replace('photo', 'thumb'))
        if os.path.exists(thumb_path):
            os.remove(thumb_path)
        image.delete()
        return HTTP.OK(data=serializer.data)