# -*- coding: utf-8 -*-
"""
/***************************************************************************
 QGuidePanel
                                 A QGIS plugin
 A convenient tool that makes it easy to perform frequently used QGIS actions such as map navigation, zooming, attribute editing, and basemap switching.
 Generated by Plugin Builder: http://g-sherman.github.io/Qgis-Plugin-Builder/
                              -------------------
        begin                : 2025-06-09
        git sha              : $Format:%H$
        copyright            : (C) 2025 by 技術チーム合同会社／TechTeam Solutions LLC
        email                : info@techteam.co.jp
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/
"""

from qgis.PyQt.QtCore import QSettings, QTranslator, QCoreApplication
from qgis.PyQt.QtGui import QIcon
from qgis.PyQt.QtWidgets import QAction
from qgis.core import (
    QgsField,
)
from qgis.PyQt.QtCore import QVariant
from PyQt5.QtCore import (
    Qt,
    QMetaType,
)
from PyQt5.QtWidgets import (
    QDockWidget,
)
from PyQt5.QtGui import (
    QStandardItemModel,
)

# Initialize Qt resources from file resources.py
from .resources import *
# Import the code for the dialog
from .q_guide_panel_dialog import QGuidePanelDialog
from .ui_qgisguide_layer import LayerPanelDialog
#from .ui_qgisguide_table import TablePanelDialog
import os.path
from .panel_control_bottun import (
    zoom_in,
    zoom_out,
    toggle_pan_mode,
    toggle_select_zoom_in,
    toggle_select_zoom_out,
    toggle_measure_mode,
    add_latlong_grid_layer,
    show_latlong_menu,
    set_map_scale_from_widget,
    update_scale_widget
)

class QGuidePanel:
    """QGIS Plugin Implementation."""

    def __init__(self, iface):
        """Constructor.

        :param iface: An interface instance that will be passed to this class
            which provides the hook by which you can manipulate the QGIS
            application at run time.
        :type iface: QgsInterface
        """
        # Save reference to the QGIS interface
        self.iface = iface
        self.canvas = iface.mapCanvas()
        # initialize plugin directory
        self.plugin_dir = os.path.dirname(__file__)
        # initialize locale
        locale = QSettings().value('locale/userLocale')[0:2]
        if locale == 'ja':
            qm_file = 'ja.qm'
        else:
            qm_file = 'en.qm'

        locale_path = os.path.join(
            self.plugin_dir,
            'i18n',
            qm_file
        )

        if os.path.exists(locale_path):
            self.translator = QTranslator()
            self.translator.load(locale_path)
            QCoreApplication.installTranslator(self.translator)

        # Declare instance attributes
        self.actions = []
        self.menu = self.tr(u'&QGIS Guide Panel')

        # Check if plugin was started the first time in current QGIS session
        # Must be set in initGui() to survive plugin reloads
        self.first_start = None

        self.pluginIsActive = False  # パネルの状態を管理するフラグ
        self.dock_widget = None  # パネルのインスタンスを保持する
        self.layerPanel = False  # レイヤーパネルの状態を管理するフラグ
        self.cursor_type = None  # カーソルの状態を管理するフラグ

    # noinspection PyMethodMayBeStatic
    def tr(self, message):
        """Get the translation for a string using Qt translation API.

        We implement this ourselves since we do not inherit QObject.

        :param message: String for translation.
        :type message: str, QString

        :returns: Translated version of message.
        :rtype: QString
        """
        # noinspection PyTypeChecker,PyArgumentList,PyCallByClass
        return QCoreApplication.translate('QGuidePanel', message)

    def add_action(
        self,
        icon_path,
        text,
        callback,
        enabled_flag=True,
        add_to_menu=True,
        add_to_toolbar=True,
        status_tip=None,
        whats_this=None,
        parent=None):
        """Add a toolbar icon to the toolbar.

        :param icon_path: Path to the icon for this action. Can be a resource
            path (e.g. ':/plugins/foo/bar.png') or a normal file system path.
        :type icon_path: str

        :param text: Text that should be shown in menu items for this action.
        :type text: str

        :param callback: Function to be called when the action is triggered.
        :type callback: function

        :param enabled_flag: A flag indicating if the action should be enabled
            by default. Defaults to True.
        :type enabled_flag: bool

        :param add_to_menu: Flag indicating whether the action should also
            be added to the menu. Defaults to True.
        :type add_to_menu: bool

        :param add_to_toolbar: Flag indicating whether the action should also
            be added to the toolbar. Defaults to True.
        :type add_to_toolbar: bool

        :param status_tip: Optional text to show in a popup when mouse pointer
            hovers over the action.
        :type status_tip: str

        :param parent: Parent widget for the new action. Defaults None.
        :type parent: QWidget

        :param whats_this: Optional text to show in the status bar when the
            mouse pointer hovers over the action.

        :returns: The action that was created. Note that the action is also
            added to self.actions list.
        :rtype: QAction
        """

        icon = QIcon(icon_path)
        action = QAction(icon, text, parent)
        action.triggered.connect(callback)
        action.setEnabled(enabled_flag)

        if status_tip is not None:
            action.setStatusTip(status_tip)

        if whats_this is not None:
            action.setWhatsThis(whats_this)

        if add_to_toolbar:
            # Adds plugin icon to Plugins toolbar
            self.iface.addToolBarIcon(action)

        if add_to_menu:
            self.iface.addPluginToMenu(
                self.menu,
                action)

        self.actions.append(action)

        return action

    def initGui(self):
        """Create the menu entries and toolbar icons inside the QGIS GUI."""

        icon_path = ':/plugins/q_guide_panel/icon.png'
        self.add_action(
            icon_path,
            text=self.tr(u'QGIS Guide Panel'),
            callback=self.run,
            parent=self.iface.mainWindow())

        # will be set False in run()
        self.first_start = True


    def unload(self):
        """Removes the plugin menu item and icon from QGIS GUI."""
        for action in self.actions:
            self.iface.removePluginMenu(
                self.tr(u'&QGIS Guide Panel'),
                action)
            self.iface.removeToolBarIcon(action)

    def onDockVisibilityChanged(self, visible):
        """パネルの表示状態が変更されたときに呼ばれる"""
        if not visible:
            self.pluginIsActive = False

    def onClosePlugin(self):
        """パネルが閉じられたときに呼ばれる（後方互換性のため残す）"""
        self.pluginIsActive = False

    def run(self):
        """Run method that performs all the real work"""

        # Create the dialog with elements (after translation) and keep reference
        # Only create GUI ONCE in callback, so that it will only load when the plugin is started
        if self.first_start == True:
            self.first_start = False
            self.dlg = QGuidePanelDialog()

            # ========================
            # ▼ パネルの追加・表示制御関連
            # ========================

            # パネルがまだ作成されていない場合は作成
            self.dock_widget = QDockWidget(self.tr("QGIS Guide Panel"), self.iface.mainWindow())
            self.dock_widget.setWidget(self.dlg)
            self.dock_widget.setFloating(True)
            # closingPlugin の代わりに visibilityChanged を使用
            self.dock_widget.visibilityChanged.connect(self.onDockVisibilityChanged)
            self.iface.addDockWidget(Qt.RightDockWidgetArea, self.dock_widget)
            
            # ▼ 横配置の位置を調整
            main_win = self.iface.mainWindow()
            main_geom = main_win.geometry()
            dock_geom = self.dock_widget.geometry()

            # 上部中央に配置（Y座標は0または10など、X座標は中央寄せ）
            x = main_geom.x() + (main_geom.width() - dock_geom.width()) // 2
            
            # 下から150ピクセル上げた位置に配置
            y = main_geom.y() + main_geom.height() - dock_geom.height() - 100
            self.dock_widget.move(x, y)

            # レイヤパネル
            self.layer_panel_dlg = LayerPanelDialog(self.iface)
            self.layer_panel_dlg.parent_plugin = self  # 親プラグインの参照を設定

            self.layer_panel_dlg.setWindowFlags(self.layer_panel_dlg.windowFlags() | Qt.WindowStaysOnTopHint)

            # パネルの初期位置をQGISウィンドウの左下に設定
            main_window = self.iface.mainWindow()
            main_geom = main_window.geometry()
            panel_geom = self.layer_panel_dlg.geometry()

            # QGISウィンドウの左下に配置
            x = main_geom.x() + 350  # 左端から20ピクセル右
            y = main_geom.y() + main_geom.height() - panel_geom.height() - 100  # 下端から100ピクセル上

            self.layer_panel_dlg.move(x, y)

            self.setup_panel_icons()

            # ========================
            # ▼ コントロールパネルのシグナル
            # ========================

            # ツールセクションのシグナル接続
            self.dlg.tbZoomIn.clicked.connect(lambda: zoom_in(self))
            self.dlg.tbZoomOut.clicked.connect(lambda: zoom_out(self))
            #self.dlg.tbMeasure.clicked.connect(lambda: activate_measure_mode(self))
            self.dlg.tbMeasure.toggled.connect(lambda checked: toggle_measure_mode(self, checked))
            
            # 区画ズームのクリックイベントを接続
            self.dlg.tbZoomInSelect.toggled.connect(lambda checked: toggle_select_zoom_in(self, checked))
            self.dlg.tbZoomOutSelect.toggled.connect(lambda checked:  toggle_select_zoom_out(self, checked))
            
            # tbMoveボタンのシグナル接続
            self.dlg.tbMove.toggled.connect(lambda checked: toggle_pan_mode(self, checked))

            # mapToolSetシグナルを接続
            #self.iface.mapCanvas().mapToolSet.connect(self.on_map_tool_changed)
            self.iface.mapCanvas().mapToolSet.connect(self.on_map_tool_changed) 

            # プラグイン起動時の現在ツール状態をボタンに反映
            current_tool = self.iface.mapCanvas().mapTool()
            self.on_map_tool_changed(current_tool)
            
            # tbLayerPanelボタンのクリックイベント
            self.dlg.tbLayerPanel.clicked.connect(self.panel_show)
            
            # ▼ tbLatLongLineの右クリックメニュー設定
            self.dlg.tbLatLongLine.setContextMenuPolicy(Qt.CustomContextMenu)
            self.dlg.tbLatLongLine.customContextMenuRequested.connect(lambda pos: show_latlong_menu(self, pos))
            self.dlg.tbLatLongLine.clicked.connect(lambda: add_latlong_grid_layer(self))

            # デフォルト値
            self.lat_step = 0.1
            self.lon_step = 0.1
            self.save_to_file = False
            
            self.update_tbLayerPanel_style()

            # QgsScaleWidget の初期化とシグナル接続
            self.dlg.mScaleWidget.setScale(self.canvas.scale())  # 現在の縮尺をウィジェットに設定
            self.dlg.mScaleWidget.scaleChanged.connect(lambda scale: set_map_scale_from_widget(self, scale))  # シグナルを接続

            # キャンバスの縮尺変更時にウィジェットを更新
            self.canvas.scaleChanged.connect(lambda: update_scale_widget(self))

            self.load_settings()

        # ========================
        # ▼ パネルの表示制御（毎回実行）
        # ========================
        
        if not self.pluginIsActive:
            self.pluginIsActive = True
            self.dock_widget.show()  # パネルを表示

        else:
            # パネルがすでに表示されている場合は非表示にする
            self.pluginIsActive = False
            self.dock_widget.hide()

    def load_settings(self):
        settings = QSettings()
        self.lat_step = float(settings.value("QGuidePanel/lat_step", 0.1))
        self.lon_step = float(settings.value("QGuidePanel/lon_step", 0.1))
        self.save_to_file = settings.value("QGuidePanel/save_to_file", False, type=bool)
        self.separate_latlon = settings.value("QGuidePanel/separate_latlon", False, type=bool)

    def panel_show(self):
        """レイヤパネルの表示/非表示を切り替える"""
        visible = not self.layer_panel_dlg.isVisible()
        if visible: 
            self.layer_panel_dlg.pbTableView.setChecked(False)
            self.layer_panel_dlg.setFixedWidth(280) # ★幅をリセット
            self.layer_panel_dlg.show()

            # テーブルビューを初期化
            self.layer_panel_dlg.tbwTable.setModel(QStandardItemModel())
        else:
            self.layer_panel_dlg.close()

        self.layer_panel_dlg.wdTable.setVisible(False)         

    def setup_panel_icons(self):
        def is_dark_mode():
            bg_color = self.dlg.palette().color(self.dlg.backgroundRole())
            brightness = (bg_color.red() * 299 + bg_color.green() * 587 + bg_color.blue() * 114) / 1000
            return brightness < 128

        if is_dark_mode():
            map_toolbutton_style = """
                QToolButton {
                    background-color: #444;
                    color: white;
                }
                QToolButton:disabled {
                    background-color: #333;
                    color: #888;
                }
            """
        else:
            map_toolbutton_style = ""

        self.layer_panel_dlg.tbLayerFolderOpen.setStyleSheet(map_toolbutton_style)
        self.layer_panel_dlg.tbEditMode.setStyleSheet(map_toolbutton_style)
        self.layer_panel_dlg.tbTableOpen.setStyleSheet(map_toolbutton_style)
        
        if is_dark_mode():
            map_pushbutton_style = """
                QPushButton {
                    color: #d8d8d8;
                }
                QPushButton:checked {
                    color: #d8d8d8;
                }
                QPushButton:disabled {
                    background-color: #333;
                    color: #646464;
                }
                QPushButton:checked:disabled {
                    color: #646464;
                }
            """
        else:
            # ライトモードではスタイルシートを適用しない（QGIS/OSに任せる）
            map_pushbutton_style = ""

        self.layer_panel_dlg.pbLayerView.setStyleSheet(map_pushbutton_style)
        self.layer_panel_dlg.pbLayerZoom.setStyleSheet(map_pushbutton_style)
        self.layer_panel_dlg.pbCallProperty.setStyleSheet(map_pushbutton_style)
        self.layer_panel_dlg.pbCallStyle.setStyleSheet(map_pushbutton_style)
        self.layer_panel_dlg.pbCallExport.setStyleSheet(map_pushbutton_style)
        self.layer_panel_dlg.pbTableView.setStyleSheet(map_pushbutton_style)
        self.layer_panel_dlg.pbCallFiltering.setStyleSheet(map_pushbutton_style)
        self.layer_panel_dlg.pbCallLabel.setStyleSheet(map_pushbutton_style)
        self.layer_panel_dlg.pbCallFieldCalculator.setStyleSheet(map_pushbutton_style)
        self.layer_panel_dlg.pbRasterCalculator.setStyleSheet(map_pushbutton_style)
        self.layer_panel_dlg.pbAllItems.setStyleSheet(map_pushbutton_style)

    def update_tbLayerPanel_style(self):
        """tbLayerPanelボタンの色を切り替える"""
        if self.layer_panel_dlg.isVisible():
            self.dlg.tbLayerPanel.setStyleSheet("""
                QToolButton {
                    background-color: dimgray;
                }
            """)
        else:
            self.dlg.tbLayerPanel.setStyleSheet("""
                QToolButton {
                    background-color: snow;
                }
            """)

    def create_field_attributes(self, provider):
        """QGISバージョンに対応したフィールド属性を追加"""
        try:
            # QGIS 3.38以降の推奨書き方
            provider.addAttributes([
                QgsField("type", QMetaType.Type.QString),
                QgsField("value", QMetaType.Type.Double)
            ])
        except (ImportError, AttributeError, TypeError):
            # QGIS 3.37以前の書き方、またはQMetaType.Type属性がない場合
            try:
                # QGIS 3.34-3.37あたりの中間的な書き方を試す
                provider.addAttributes([
                    QgsField("type", QMetaType.QString),
                    QgsField("value", QMetaType.Double)
                ])
            except (ImportError, AttributeError, TypeError):
                # 最も古い書き方（QGIS 3.33以前）
                provider.addAttributes([
                    QgsField("type", QVariant.String),
                    QgsField("value", QVariant.Double)
                ])

    def update_layer_panel_button(self, visible):
        """レイヤーパネルの表示状態に応じてツールボタンの状態を更新"""
        if hasattr(self, 'dlg') and hasattr(self.dlg, 'tbLayerPanel'):
            self.dlg.tbLayerPanel.setChecked(visible)
            self.layerPanel = visible

            # スタイルシートを適用
            if visible:
                # チェック状態（表示中）
                self.dlg.tbLayerPanel.setStyleSheet("""
                    QToolButton {
                        background-color: dimgray;
                    }
                """)
            else:
                # 通常状態（非表示）
                self.dlg.tbLayerPanel.setStyleSheet("""
                    QToolButton {
                        background-color: snow;
                    }
                """)

    def on_map_tool_changed(self, tool):
        """マップツールが変更されたら、その種類を判別して保存"""
        debug_mode = False
        
        tool_name = tool.__class__.__name__ if tool else "None"
        
        if tool_name == "QgsMapToolPan":
            self.cursor_type = "pan"
        elif tool_name == "QgsMapToolZoom":
            if hasattr(tool, 'zoomIn'):
                if tool.zoomIn():
                    self.cursor_type = "zoom_in"
                else:
                    self.cursor_type = "zoom_out"
            elif self.iface.actionZoomIn().isChecked():
                self.cursor_type = "zoom_in"
            elif self.iface.actionZoomOut().isChecked():
                self.cursor_type = "zoom_out"
            else:
                self.cursor_type = "zoom_unknown"
        elif self.iface.actionMeasure().isChecked():
            self.cursor_type = "measure"
        elif tool_name == "QgsMapToolIdentify":
            self.cursor_type = "identify"
        elif tool_name == "QgsMapToolDigitizeFeature":
            self.cursor_type = "add_feature"
        elif tool_name == "QgsMapToolAdvancedDigitizing":
            self.cursor_type = "vertex_tool"
        elif "Select" in tool_name or tool_name in ["QgsMapToolSelectFeatures", "QgsMapToolSelectRectangle", "QgsMapToolSelectPolygon", "QgsMapToolSelectFreehand"]:
            self.cursor_type = "select_feature"
        elif tool_name == "QgsMapTool":
            try:
                tool_str = str(tool)
                if "select" in tool_str.lower():
                    self.cursor_type = "select_feature"
                elif "measure" in tool_str.lower():
                    self.cursor_type = "measure"
                else:
                    active_layer = self.iface.activeLayer()
                    if active_layer and hasattr(active_layer, 'type') and active_layer.type() == 0:
                        self.cursor_type = "select_feature"
                    else:
                        self.cursor_type = "generic_tool"
            except:
                self.cursor_type = "generic_tool"
        else:
            self.cursor_type = f"unknown_{tool_name}"

        self._update_button_states()
        
        if debug_mode:
            print(f"ツール変更: {self.cursor_type} (クラス名: {tool_name})")

    def _update_button_states(self):
        """cursor_typeに基づいてボタンの状態を更新"""
        # シグナルを一時的に切断
        try:
            self.dlg.tbMove.toggled.disconnect()
            self.dlg.tbZoomInSelect.toggled.disconnect()
            self.dlg.tbZoomOutSelect.toggled.disconnect()
            self.dlg.tbMeasure.toggled.disconnect()
        except:
            pass

        try:
            # tbMoveの状態更新
            if self.cursor_type == "pan":
                self.dlg.tbMove.setChecked(True)
                self.dlg.tbMove.setStyleSheet("QToolButton { background-color: dimgray; }")
            else:
                self.dlg.tbMove.setChecked(False)
                self.dlg.tbMove.setStyleSheet("QToolButton { background-color: snow; }")

            # tbZoomInSelectの状態更新
            if self.cursor_type == "zoom_in":
                self.dlg.tbZoomInSelect.setChecked(True)
                self.dlg.tbZoomInSelect.setStyleSheet("QToolButton { background-color: dimgray; }")
            else:
                self.dlg.tbZoomInSelect.setChecked(False)
                self.dlg.tbZoomInSelect.setStyleSheet("QToolButton { background-color: snow; }")

            # tbZoomOutSelectの状態更新
            if self.cursor_type == "zoom_out":
                self.dlg.tbZoomOutSelect.setChecked(True)
                self.dlg.tbZoomOutSelect.setStyleSheet("QToolButton { background-color: dimgray; }")
            else:
                self.dlg.tbZoomOutSelect.setChecked(False)
                self.dlg.tbZoomOutSelect.setStyleSheet("QToolButton { background-color: snow; }")

            # tbMeasureの状態更新
            if self.cursor_type == "measure":
                self.dlg.tbMeasure.setChecked(True)
                self.dlg.tbMeasure.setStyleSheet("QToolButton { background-color: dimgray; }")
            else:
                self.dlg.tbMeasure.setChecked(False)
                self.dlg.tbMeasure.setStyleSheet("QToolButton { background-color: snow; }")
        finally:
            # シグナルを再接続
            self.dlg.tbZoomInSelect.toggled.connect(lambda checked: toggle_select_zoom_in(self, checked))
            self.dlg.tbZoomOutSelect.toggled.connect(lambda checked: toggle_select_zoom_out(self, checked))
            self.dlg.tbMove.toggled.connect(lambda checked: toggle_pan_mode(self, checked))
            self.dlg.tbMeasure.toggled.connect(lambda checked: toggle_measure_mode(self, checked))