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

"""
    重构 bxplorer_base
"""

import os
import subprocess
from win32com.shell import shell, shellcon
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QMainWindow, QHeaderView, QFileDialog, QPushButton, QDesktopWidget
from PyQt5.QtWidgets import QTableWidgetItem, QAbstractItemView, QItemDelegate, QMenu

from bxplorer_base import Ui_MainWindow
from bxplorer_data import BxplorerData

class Bxplorer(QMainWindow, Ui_MainWindow):
    ''' 重构 bxplorer_base '''

    def __init__(self, data_path=None):
        super().__init__()

        # 初始化界面
        self.setupUi(self)

        # 初始化数据
        self.bxplorer_data = BxplorerData(data_path)

        # 初始化界面风格
        self.__set_center()
        self.__set_widget_style()

        # 设置响应事件
        self.__set_event()

        # 初始化界面展示内容
        self.__show_tw_file()
        self.__show_tw_root()

        # self.tw_file.itemChanged.connect(self.__edit_tw_file)       # 文件表格用户编辑响应

        # 设置tableWidget的显示内容
        # self.__update_tw_root()

    def __set_center(self):
        ''' 设置主窗口初始化位置 '''

        screen = QDesktopWidget().screenGeometry()
        width = screen.width() - 200
        height = screen.height() - 200
        self.resize(width, height)
        self.move(100, 100)

    def __set_widget_style(self):
        ''' 设置小部件风格 '''

        # 设置文件窗口风格
        ## 获取列名和列宽
        column_name = self.bxplorer_data.property['name']
        column_size = self.bxplorer_data.property['length']
        # 设置列名
        self.tw_file.setColumnCount(len(column_name))
        self.tw_file.setHorizontalHeaderLabels(column_name)
        # 设置列宽
        self.tw_file.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeToContents)
        for index, length in enumerate(column_size):
            if length == 0:
                continue
            self.tw_file.horizontalHeader().setSectionResizeMode(index, QHeaderView.Interactive)
            self.tw_file.setColumnWidth(index, length)
        # 设置编辑状态
        self.tw_file.setEditTriggers(QAbstractItemView.DoubleClicked)
        self.tw_file.setItemDelegateForColumn(column_name.index('名称'), EmptyDelegate(self))
        self.tw_file.setItemDelegateForColumn(column_name.index('格式'), EmptyDelegate(self))
        self.tw_file.setItemDelegateForColumn(column_name.index('路径'), EmptyDelegate(self))

        # 设置文件夹窗口风格
        self.tw_root.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
        self.tw_root.horizontalHeader().setSectionResizeMode(1, QHeaderView.Interactive)
        self.tw_file.setColumnWidth(1, 100)

    def __show_tw_file(self):
        ''' 展示文件框体内容 '''

        self.tw_file.blockSignals(True)     # 阻塞信号传递

        # 获取数据
        data = self.bxplorer_data.read()
        data_file = data['File']

        # 设置表格行数
        row_count = len(data_file)
        self.tw_file.setRowCount(row_count)

        # 设置表格内容
        column_name = self.bxplorer_data.property['name']
        for row, file in enumerate(data_file):

            # 获取基本属性
            file_code = data_file[file]['code']
            file_extension = data_file[file]['extension']
            file_name = data_file[file]['name']
            file_path = file
            file_size = data_file[file]['size']

            # 展示基本属性
            self.tw_file.setItem(row, column_name.index('名称'), QTableWidgetItem(file_name))
            self.tw_file.setItem(row, column_name.index('格式'), QTableWidgetItem(file_extension))
            self.tw_file.setItem(row, column_name.index('路径'), QTableWidgetItem(file_path))
            self.tw_file.setItem(row, column_name.index('大小'), QTableWidgetItem(file_size))
            self.tw_file.setCellWidget(row, column_name.index('播放'), self.__pd_play(file_path))

            # 展示备忘属性
            if file_code in data['Backups']:
                for key, value in data['Backups'][file_code].items():
                    self.tw_file.setItem(row, column_name.index(key), QTableWidgetItem(value))

        self.tw_file.blockSignals(False)     # 接触信号阻塞

    def __show_tw_root(self):
        ''' 展示文件夹框体内容 '''

        # 获取数据
        data = self.bxplorer_data.read()

        # 设置表格行数
        row_count = len(data['Root'])
        self.tw_root.setRowCount(row_count)

        # 设置表格内容
        for row, root in enumerate(data['Root']):
            # root内容
            self.tw_root.setItem(row, 0, QTableWidgetItem(str(root)))
            # 删除按钮
            self.tw_root.setCellWidget(row, 1, self.__pb_delete_root(row))

    def __set_event(self):
        ''' 设置响应事件 '''

        # “打开按钮”
        self.pb_open.clicked.connect(self.__new_root)

        # 文件框体，鼠标右键点击响应
        self.tw_file.setContextMenuPolicy(Qt.CustomContextMenu)
        self.tw_file.customContextMenuRequested.connect(self.__tw_file_requested)

        self.tw_file.itemChanged.connect(self.__edit_tw_file)       # 文件表格用户编辑响应

    def __play(self, file):
        ''' 播放 '''

        cmd = '"%s" "%s"' % (self.bxplorer_data.player, file)
        subprocess.Popen(cmd)

    def __pd_play(self, file):
        ''' 播放按钮 '''

        pd_play = QPushButton('Play')
        pd_play.clicked.connect(lambda: self.__play(file))
        return pd_play

    def __new_root(self):
        ''' 新增root '''

        # 获取新文件夹路径
        root = QFileDialog.getExistingDirectory(self, '选择文件夹', os.getcwd())
        if root == '' or root is None:
            return

        # 更新数据
        self.bxplorer_data.append_root(root)

        # 在表格中展示数据
        self.__show_tw_file()
        self.__show_tw_root()

    def __delete_root(self, index):
        ''' 删除root '''

        # 获取删除的文件夹路径
        data = self.bxplorer_data.read()
        root = data['Root'][index]

        # 更新数据
        self.bxplorer_data.delete_root(root)

        # 在表格中展示数据
        self.__show_tw_file()
        self.__show_tw_root()

    def __pb_delete_root(self, index):
        ''' 删除root按钮 '''

        pb_delete_root = QPushButton('删除')
        pb_delete_root.clicked.connect(lambda: self.__delete_root(index))
        return pb_delete_root

    def __update_tw_file(self):
        ''' 设置tw_file '''

        # 阻塞信号，防止触发 self.tw_file.itemChanged.connect(self.__edit_tw_file)
        self.tw_file.blockSignals(True)
        column_name = self.bxplorer_data.property['name']
        # 获取数据
        data = self.bxplorer_data.read()

        # 设置表格行数
        row_count = len(data['File'])
        self.tw_file.setRowCount(row_count)

        # 设置表格内容
        for row, file in enumerate(data['File']):

            file_path = file
            file_name = data['File'][file]['name']
            file_extension = data['File'][file]['extension']
            file_size = data['File'][file]['size']

            self.tw_file.setItem(row, column_name.index('名称'), QTableWidgetItem(file_name))
            self.tw_file.setItem(row, column_name.index('格式'), QTableWidgetItem(file_extension))
            self.tw_file.setItem(row, column_name.index('路径'), QTableWidgetItem(file_path))
            self.tw_file.setItem(row, column_name.index('大小'), QTableWidgetItem(file_size))
            self.tw_file.setCellWidget(row, column_name.index('播放'), self.__pd_play(file_path))

        # 鼠标右键
        self.tw_file.setContextMenuPolicy(Qt.CustomContextMenu)
        self.tw_file.customContextMenuRequested.connect(self.__tw_file_requested)

        # 退出阻塞模式
        self.tw_file.blockSignals(False)

    def __tw_file_requested(self, pos):
        ''' 文件框体的右键响应 '''

        self.tw_file.blockSignals(True)     # 阻塞信号传递

        # 获取行列号
        row = self.tw_file.selectionModel().selection().indexes()[0].row()
        column = self.tw_file.selectionModel().selection().indexes()[0].column()

        # 获取列名
        column_names = self.bxplorer_data.property['name']
        column_name = column_names[column]

        # 对于在 self.bxplorer_data.choices 中的列，设置菜单响应
        if column_name in self.bxplorer_data.choices:

            # 设置菜单
            menu = QMenu()
            actions = []
            choices = self.bxplorer_data.choices[column_name]
            for choice in choices:
                action = menu.addAction(choice)
                actions.append(action)
            screen_pos = self.tw_file.mapToGlobal(pos)
            action = menu.exec(screen_pos)

            # 用户点击菜单项后
            if action is not None:
                # 即时展示数据
                value = choices[actions.index(action)]
                self.tw_file.setItem(row, column, QTableWidgetItem(value))
                # 回填数据
                file = self.tw_file.item(row, column_names.index('路径')).text()
                data = self.bxplorer_data.read()
                code = data['File'][file]['code']
                self.bxplorer_data.update_backups(code, column_name, value)

        # 列0（即“名称”列）的右键菜单
        if column == 0:

            # 设置菜单
            menu = QMenu()
            actions = []
            choices = ['重命名', '删除']
            for choice in choices:
                action = menu.addAction(choice)
                actions.append(action)
            screen_pos = self.tw_file.mapToGlobal(pos)
            action = menu.exec(screen_pos)

            # 用户点击菜单项后
            if action is not None:
                index = actions.index(action)
                file = self.tw_file.item(row, column_names.index('路径')).text()
                if index == 0:
                    self.__rename_file(file)
                elif index == 1:
                    self.__delete_file(file)
                else:
                    pass

        self.tw_file.blockSignals(False)     # 解除信号阻塞

    def __edit_tw_file(self, item):
        ''' 用户编辑tw_file '''

        # 获取行列号和数据
        row = item.row()
        column = item.column()
        text = item.text()

        # 获取列名
        column_names = self.bxplorer_data.property['name']
        column_name = column_names[column]

        # 更新数据
        file = self.tw_file.item(row, column_names.index('路径')).text()
        data = self.bxplorer_data.read()
        code = data['File'][file]['code']
        self.bxplorer_data.update_backups(code, column_name, text)

    def __rename_file(self, file):
        ''' 重命名一个文件 '''
        pass

    def __delete_file(self, file):
        ''' 删除一个文件 '''

        # 删除文件到回收站
        shell.SHFileOperation((0, shellcon.FO_DELETE, file, None, \
            shellcon.FOF_SILENT | shellcon.FOF_ALLOWUNDO | shellcon.FOF_NOCONFIRMATION, None, None))

        # 从数据中删除文件
        data = self.bxplorer_data.read()
        del data['File'][file]
        self.bxplorer_data.write(data)

        # 更新文件框体展示
        self.__show_tw_file()

class EmptyDelegate(QItemDelegate):
    def __init__(self, parent):
        super(EmptyDelegate, self).__init__(parent)

    def createEditor(self, QWidget, QStyleOptionViewItem, QModelIndex):
        return None
