# ##### BEGIN GPL LICENSE BLOCK #####
#
#  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.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with this program; if not, write to the Free Software Foundation,
#  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####
#
# <pep8 compliant>
#
# ----------------------------------------------------------
# Author: Zeffii
# Modified by: Alan Odom (Clockmender) & Rune Morling (ermo)
# ----------------------------------------------------------
#
#
import bpy
import bmesh
from mathutils.geometry import intersect_line_plane
from .pdt_msg_strings import (
    PDT_ERR_NOINT,
    PDT_ERR_EDOB_MODE,
    PDT_ERR_SEL_1_E_1_F,
)
from .pdt_functions import oops


def failure_message(context):
    """Warn to the user to select 1 edge and 1 face.

    Args:
         context: Blender bpy.context instance.

    Returns:
        Nothing.
    """

    pg = context.scene.pdt_pg
    pg.error = f"{PDT_ERR_SEL_1_E_1_F}"
    context.window_manager.popup_menu(oops, title="Error", icon="ERROR")


def failure_message_on_plane(context):
    """Report an informative error message in a popup.

    Args:
         context: Blender bpy.context instance.

    Returns:
        Nothing.
    """

    pg = context.scene.pdt_pg
    pg.error = f"{PDT_ERR_NOINT}"
    context.window_manager.popup_menu(oops, title="Error", icon="ERROR")

def extend_vertex(context):
    """Computes Edge Extension to Face.

    Args:
        context: Blender bpy.context instance.

    Returns:
        Nothing.
    """

    obj = bpy.context.edit_object
    pg = context.scene.pdt_pg

    if all([bool(obj), obj.type == "MESH", obj.mode == "EDIT"]):
        object_data = obj.data
        bm = bmesh.from_edit_mesh(object_data)
        verts = bm.verts
        faces = bm.faces

        planes = [f for f in faces if f.select]
        if not len(planes) == 1:
            failure_message(context)
            return

        plane = planes[0]
        plane_vert_indices = plane.verts[:]
        all_selected_vert_indices = [v for v in verts if v.select]

        plane_verts = set(plane_vert_indices)
        all_verts = set(all_selected_vert_indices)
        diff_verts = all_verts.difference(plane_verts)
        diff_verts = list(diff_verts)

        if not len(diff_verts) == 2:
            failure_message(context)
            return

        (v1_ref, v1), (v2_ref, v2) = [(i, i.co) for i in diff_verts]

        plane_co = plane.calc_center_median()
        plane_no = plane.normal

        new_co = intersect_line_plane(v1, v2, plane_co, plane_no, False)

        if new_co:
            new_vertex = verts.new(new_co)
            a_len = (v1 - new_co).length
            b_len = (v2 - new_co).length

            vertex_reference = v1_ref if (a_len < b_len) else v2_ref
            bm.edges.new([vertex_reference, new_vertex])
            bmesh.update_edit_mesh(object_data, True)

        else:
            failure_message_on_plane(context)
    else:
        pg.error = f"{PDT_ERR_EDOB_MODE},{obj.mode})"
        context.window_manager.popup_menu(oops, title="Error", icon="ERROR")
        return


class PDT_OT_EdgeToFace(bpy.types.Operator):
    """Extend Selected Edge to Projected Intersection with Selected Face."""

    bl_idname = "pdt.edge_to_face"
    bl_label = "Extend Edge to Face"
    bl_options = {"REGISTER", "UNDO"}

    @classmethod
    def poll(cls, context):
        """Only allow this to work if a mesh is selected in EDIT mode.

        Args:
            context: Blender bpy.context instance.

        Returns:
            Boolean.
        """

        obj = context.object
        if obj is None:
            return False
        return all([bool(obj), obj.type == "MESH", obj.mode == "EDIT"])

    def execute(self, context):
        """Extends Disconnected Edge to Intersect with Face.

        Args:
            context: Blender bpy.context instance.

        Returns:
            Status Set.
        """

        pg = context.scene.pdt_pg
        pg.command = f"etf"
        return {"FINISHED"}
