# -*- coding: utf-8 -*-
# -----------------------------------------------------------------------------
# Copyright 2016 Continuum Analytics, Inc.
#
# May be copied and distributed freely only as part of an Anaconda or
# Miniconda installation.
# -----------------------------------------------------------------------------
"""Environment creation, import, deletion dialogs."""

# Standard library imports
import os
import sys

# Third party imports
from qtpy.compat import getopenfilename
from qtpy.QtWidgets import (QGridLayout, QHBoxLayout, QLabel, QLineEdit,
                            QVBoxLayout)
import yaml

# Local imports
from anaconda_navigator.widgets import (ButtonDanger, ButtonNormal,
                                        ButtonPrimary, CheckBoxBase,
                                        ComboBoxBase, SpacerHorizontal,
                                        SpacerVertical)
from anaconda_navigator.widgets.dialogs import DialogBase


class ImportDialog(DialogBase):
    """Import environment from environment specification dialog."""

    CONDA_ENV_FILES = 'Conda environment files (*.yaml *.yml)'
    CONDA_SPEC_FILES = 'Conda explicit specification files (*.txt)'
    PIP_REQUIREMENT_FILES = 'Pip requirement files (*.txt)'

    def __init__(self, parent=None, environments=None):
        """Import environment from environment specification dialog."""
        super(ImportDialog, self).__init__(parent=parent)

        self.environments = environments if environments else []
        self.selected_file_filter = None
        self.path = None

        # Widgets
        self.label_name = QLabel("Environment name")
        self.label_path = QLabel("Specification File")
        self.text_name = QLineEdit()
        self.text_path = QLineEdit()
        self.button_path = ButtonNormal("")
        self.button_cancel = ButtonNormal('Cancel')
        self.button_ok = ButtonPrimary('Import')

        # Widgets setup
        self.button_path.setObjectName('import')
        self.button_ok.setDefault(True)
        self.text_path.setPlaceholderText("File to import from")
        self.text_name.setPlaceholderText("New environment name")
        self.setMinimumWidth(380)
        self.setWindowTitle("Import new environment")

        # Layouts
        layout_infile = QHBoxLayout()
        layout_infile.addWidget(self.text_path)
        layout_infile.addWidget(SpacerHorizontal())
        layout_infile.addWidget(self.button_path)

        layout_grid = QGridLayout()
        layout_grid.addWidget(self.label_name, 0, 0)
        layout_grid.addWidget(SpacerHorizontal(), 0, 1)
        layout_grid.addWidget(self.text_name, 0, 2)
        layout_grid.addWidget(SpacerVertical(), 1, 0)
        layout_grid.addWidget(self.label_path, 2, 0)
        layout_grid.addWidget(SpacerHorizontal(), 2, 1)
        layout_grid.addLayout(layout_infile, 2, 2)

        layout_buttons = QHBoxLayout()
        layout_buttons.addStretch()
        layout_buttons.addWidget(self.button_cancel)
        layout_buttons.addWidget(SpacerHorizontal())
        layout_buttons.addWidget(self.button_ok)

        layout = QVBoxLayout()
        layout.addLayout(layout_grid)
        layout.addWidget(SpacerVertical())
        layout.addWidget(SpacerVertical())
        layout.addLayout(layout_buttons)

        self.setLayout(layout)

        # Signals
        self.button_ok.clicked.connect(self.accept)
        self.button_cancel.clicked.connect(self.reject)
        self.button_path.clicked.connect(self.choose)
        self.text_path.textChanged.connect(self.refresh)
        self.text_name.textChanged.connect(self.refresh)

        # Setup
        self.refresh()

    def choose(self):
        """Display file dialog to select environment specification."""
        path, selected_filter = getopenfilename(
            caption="Import Environment",
            basedir=os.path.expanduser('~'),
            parent=None,
            filters="{0};;{1};;{2}".format(self.CONDA_ENV_FILES,
                                           self.CONDA_SPEC_FILES,
                                           self.PIP_REQUIREMENT_FILES))

        if path:
            name = self.text_name.text()
            self.selected_file_filter = selected_filter
            self.text_path.setText(path)
            self.refresh(path)

            # Try to get the name key of the file if an environment.yaml file
            if selected_filter == self.CONDA_ENV_FILES:
                try:
                    with open(path, 'r') as f:
                        raw = f.read()
                    data = yaml.load(raw)
                    name = data.get('name', name)
                except Exception:
                    pass
            self.text_name.setText(name)

    def refresh(self, text=''):
        """Update the status of buttons based on combobox selection."""
        text = self.text_name.text()
        self.path = self.text_path.text()

        if (text and self.path and os.path.exists(self.path) and
                text not in self.environments):
            self.button_ok.setDisabled(False)
            self.button_ok.setDefault(True)
        else:
            self.button_ok.setDisabled(True)
            self.button_cancel.setDefault(True)


class CreateDialog(DialogBase):
    """Create new environment dialog."""

    def __init__(self, parent=None, path=None, environments=None):
        """Create new environment dialog."""
        super(CreateDialog, self).__init__(parent=parent)

        self.environments = environments

        # Widgets
        self.label_name = QLabel("Environment name")
        self.check_python = CheckBoxBase("Python")
        self.check_r = CheckBoxBase('R')
        self.label_version = QLabel("Python version")
        self.text_name = QLineEdit()
        self.combo_version = ComboBoxBase()
        self.button_ok = ButtonPrimary('Create')
        self.button_cancel = ButtonNormal('Cancel')

        # Widgets setup
        self.check_python.setChecked(True)
        self.check_r.setChecked(False)
        self.text_name.setPlaceholderText("New environment name")
        self.setMinimumWidth(380)
        self.setWindowTitle("Create new environment")

        # TODO: Possible set of python versions?
        versions = ['2.6', '2.7', '3.3', '3.4', '3.5']
        now = "{}.{}".format(sys.version_info.major, sys.version_info.minor)

        if now not in versions:
            # Guard against non-standard version, or the coming 3.6
            versions.append(now)
            versions.sort()

        self.combo_version.addItems(versions)
        self.combo_version.setCurrentIndex(versions.index(now))

        # Layouts
        check = QHBoxLayout()
        check.addWidget(self.check_python)
        check.addWidget(self.check_r)
        check.addStretch()
        grid = QGridLayout()
        grid.addWidget(self.label_name, 0, 0)
        grid.addWidget(SpacerHorizontal(), 0, 1)
        grid.addWidget(self.text_name, 0, 2)
        grid.addWidget(SpacerVertical(), 1, 0)
        grid.addLayout(check, 2, 2)
        grid.addWidget(SpacerVertical(), 3, 0)
        grid.addWidget(self.label_version, 4, 0)
        grid.addWidget(SpacerHorizontal(), 4, 1)
        grid.addWidget(self.combo_version, 4, 2)
        grid.addWidget(SpacerVertical(), 5, 0)

        layout_buttons = QHBoxLayout()
        layout_buttons.addStretch()
        layout_buttons.addWidget(self.button_cancel)
        layout_buttons.addWidget(SpacerHorizontal())
        layout_buttons.addWidget(self.button_ok)

        main_layout = QVBoxLayout()
        main_layout.addLayout(grid)
        main_layout.addWidget(SpacerVertical())
        main_layout.addWidget(SpacerVertical())
        main_layout.addLayout(layout_buttons)

        self.setLayout(main_layout)

        # Signals
        self.button_ok.clicked.connect(self.accept)
        self.button_cancel.clicked.connect(self.reject)
        self.text_name.textChanged.connect(self.refresh)
        self.check_python.stateChanged.connect(self.refresh)
        self.check_r.stateChanged.connect(self.refresh)

        # Setup
        self.refresh()

    def refresh(self, text=''):
        """Update status of buttons based on combobox selection."""
        text = self.text_name.text().strip()
        if self.environments:
            if ((text and text not in self.environments) and
                    (self.check_r.checkState() or
                     self.check_python.checkState())):
                self.button_ok.setDisabled(False)
            else:
                self.button_ok.setDisabled(True)
        self.combo_version.setEnabled(self.check_python.checkState())


class CloneDialog(DialogBase):
    """Clone environment dialog."""

    def __init__(self, parent=None, environments=None):
        """Clone environment dialog."""
        super(CloneDialog, self).__init__(parent=parent)
        self.environments = environments

        # Widgets
        self.label_name = QLabel("Environment name")
        self.text_name = QLineEdit()
        self.button_ok = ButtonPrimary('Clone')
        self.button_cancel = ButtonNormal('Cancel')

        # Widget setup
        self.setMinimumWidth(380)
        self.setWindowTitle("Clone environment")
        self.text_name.setPlaceholderText("New environment name")

        # Layouts
        layout_text = QHBoxLayout()
        layout_text.addWidget(self.label_name)
        layout_text.addWidget(SpacerHorizontal())
        layout_text.addWidget(self.text_name)

        layout_buttons = QHBoxLayout()
        layout_buttons.addStretch()
        layout_buttons.addWidget(self.button_cancel)
        layout_buttons.addWidget(SpacerHorizontal())
        layout_buttons.addWidget(self.button_ok)

        layout = QVBoxLayout()
        layout.addLayout(layout_text)
        layout.addWidget(SpacerVertical())
        layout.addWidget(SpacerVertical())
        layout.addLayout(layout_buttons)

        self.setLayout(layout)

        # Signals
        self.text_name.textChanged.connect(self.refresh)
        self.button_ok.clicked.connect(self.accept)
        self.button_cancel.clicked.connect(self.reject)

    def refresh(self, text=''):
        """Update status of buttons based on combobox selection."""
        text = self.text_name.text().strip()
        if self.environments:
            if text and text not in self.environments:
                self.button_ok.setDisabled(False)
            else:
                self.button_ok.setDisabled(True)


class RemoveDialog(DialogBase):
    """Remove existing environment dialog."""

    def __init__(self, parent=None, environment=None):
        """Remove existing environment dialog."""
        super(RemoveDialog, self).__init__(parent=parent)

        # Widgets
        self.button_cancel = ButtonNormal('Cancel')
        self.button_remove = ButtonDanger('Remove')
        self.label_environment = QLabel('Do you want to remove environment '
                                        '<b>"{0}"</b>'.format(environment))

        # Setup
        self.setWindowTitle('Remove environment')
        self.setMinimumWidth(380)

        # Layouts
        layout_buttons = QHBoxLayout()
        layout_buttons.addStretch()
        layout_buttons.addWidget(self.button_cancel)
        layout_buttons.addWidget(SpacerHorizontal())
        layout_buttons.addWidget(self.button_remove)

        layout = QVBoxLayout()
        layout.addWidget(self.label_environment)
        layout.addWidget(SpacerVertical())
        layout.addWidget(SpacerVertical())
        layout.addLayout(layout_buttons)
        self.setLayout(layout)

        # Signals
        self.button_remove.clicked.connect(self.accept)
        self.button_cancel.clicked.connect(self.reject)


# --- Local testing
# -----------------------------------------------------------------------------
def test():   # pragma: no cover
    """Run local tests."""
    from anaconda_navigator.utils.qthelpers import qapplication

    app = qapplication()
    widget_create = CreateDialog(parent=None, environments=['root', 'boom'])
    widget_create.show()

    widget_clone = CloneDialog(parent=None)
    widget_clone.show()

    widget_import = ImportDialog(parent=None, environments=['root', 'boom'])
    widget_import.show()

    widget_remove = RemoveDialog(parent=None, environment='Test')
    widget_remove.show()

    app.exec_()


if __name__ == '__main__':   # pragma: no cover
    test()
