"""[ Pair Manager ]"""
import datetime

import bpy
import mathutils
from ..AngleMeasurement.CalculateAngle import get_angle
from ..AngleMeasurement.RP1DClustering import ClusteringMeanRP1D
from ..VolatileStorage.ColorManager import ColorPairs
from .RegionManager import RegionManager

class PairManager(object):
    def __init__(self, backup_pointer):
        self.context = bpy.context
        self.bso = bpy.context.scene.cs_overall_VG_
        self.bsa = bpy.context.active_object.cs_individual_VG_
        self.bsp = backup_pointer
        self.material_1 = None
        self.material_2 = None
        self.n1, self.n2, self.patch_normal_1, self.patch_normal_2 = None, None, None, None
        self.material_index_1 = 0
        self.check_index = 0
        self.material_index_2 = 0
        
    def load_from_backup(self, backup_pointer):
        self.bsp = backup_pointer
                
        self.material_1 = RegionManager(self.bsp.patch_A)
        self.material_2 = RegionManager(self.bsp.patch_B)

    def construct_new(self, c_polygon_pointer=None):
        #self.add_pair_to_blender_storage()
        if c_polygon_pointer is None:
            # give the coordinates of the center of the pair
            self.check_index = 0
        else:
            # Pass in the center poly pointer
            #self.c_polygon_pointer = c_polygon_pointer
            self.check_index = c_polygon_pointer.index
            self.bsp.center = list(c_polygon_pointer.center)

        #self.add_pair_to_blender_storage()
        self.bsp.context_object = bpy.context.active_object
        self.bsp.created_since_epoch = datetime.datetime.now().timestamp()
        
        self.create_new_material_pair()
    
    def set_name(self, break_index):
        self.bsp.break_index = break_index

    def create_new_material_pair(self):
        # set the color objects from the pair list
        o_color1, o_color2 = self.generate_color_objects()
        
        self.bsp.context_object = self.context.active_object
        
        self.bsp.patch_A.context_object = self.context.active_object
        self.bsp.patch_B.context_object = self.context.active_object
        
        self.bsp.patch_A.default_color = list(o_color1)
        self.bsp.patch_B.default_color = list(o_color2)
        
        self.bsp.patch_A.name = str(self.bsp.name + " Face (1)")
        self.bsp.patch_B.name = str(self.bsp.name + " Face (2)")
        # create the materials
        self.material_1 = RegionManager(self.bsp.patch_A)
        self.material_2 = RegionManager(self.bsp.patch_B)
        
        
        self.bsp.side_1_material = self.material_1.bsp.material
        self.bsp.side_2_material = self.material_2.bsp.material
    
    def generate_color_objects(self):
        #TODOO: FIX THIS SO IT NO LONGER REQUIRES ACTIVE CONTEXT

        # Create color 1 & color 2
        cp = ColorPairs()
        col1 = mathutils.Color(cp.return_active_pairs()[self.bsa.cp_index][0])
        col2 = mathutils.Color(cp.return_active_pairs()[self.bsa.cp_index][1])
        # Increment the counter
        self.bsa.cp_index += 1
        return col1, col2

    def refresh_material_indexes(self):
        # refresh material indexes.
        self.material_index_1 = self.material_1.get_material_index()
        self.material_index_2 = self.material_2.get_material_index()
        return self.material_index_1, self.material_index_2
    
    def get_current_face_data(self):
        # get the Faces
        faces1 = self.material_1.update_faces_with_material()
        faces2 = self.material_2.update_faces_with_material()
        return faces1, faces2
    
    def get_angle(self):
        # get the Normals and Centroids
        center1, normal1 = self.material_1.get_face_mathematical_components()
        center2, normal2 = self.material_2.get_face_mathematical_components()
        
        # get the angle
        self.bsp.theta, self.patch_normal_1, self.patch_normal_2 = get_angle(
            center1, center2,
            normal1, normal2)
    
    def apply_to_face_pair_by_indexes(self, F1, F2):
        self.material_1.apply_to_faces_by_face_index(F1)
        self.material_2.apply_to_faces_by_face_index(F2)

    def apply_pair_within_region(self, CNs, J):
        #Virtual goniometer
        #   P = nx3 numpy array of vertices of points in patch
        #   N = nx3 array of vertex normals
        #   Can also use N as face normals, and P as face centroids
        #   T = Number of random projections to use (default T=100)
        P = CNs[0, J] #mx3 array of x,y,z coordinates for all m vertices in patch
        N = CNs[1, J] #mx3 array of x,y,z coordinates of
        # unit outward normal vectors to vertices in patch
        T = int(self.bso.number_of_random_projections)
        #Output:f
        #   C = Clusters (C==1 and C==2 are the two detected clusters)
        C, self.n1, self.n2, self.bsp.theta = ClusteringMeanRP1D(P, N, T)
        #P1 = P[C==1,:]     #P2 = P[C==2,:]
        J1 = J[C == 1]
        J2 = J[C == 2]
        
        self.apply_to_face_pair_by_indexes(J1, J2)
        

        print(self.bsp.name + " has a theta of " +str(self.bsp.theta))

    
    def destroy(self):
        
        self.material_1.destroy()
        self.material_2.destroy()
        self.bsa.material_pairs.remove(self.bsp.index)
