__author__ = 'shenojia'

import sys
import numpy as np
from math import floor
from matplotlib.path import Path
from matplotlib.patches import PathPatch
sys.path.insert(0, '.')
sys.path.insert(0, '..')
from R12_36211.SLOT import SLOT
from R12_36xxx.TypesDefition import *
from R12_36xxx.HighLayer import conf

class PCFICH:

    def __init__(self,subFrameNumber:int,subFrameType:SubFrameType, MBSFN:bool, PRS:bool):
        # self.res = self._initRes(slot)
        self.res = []
        self.n__s = None
        self.n = subFrameNumber
        self.subFrameType = subFrameType
        self.MBSFN = MBSFN
        self.PRS = PRS
        self.N__OFDM =  self._initNumOfOfdmSymb4PDCCH(conf.numOfOfdmSymb4PDCCH)
        self.patch, self.codes, self.vertices = [],[],[]

    def _initRes(self, slot:SLOT):
        """
        6.7.4	Mapping to resource elements
        :param slot:
        :return:
        """
        res = []
        if slot.n__s!=0:
            return None
        else:
            self.n__s = slot.n__s
        l = 0
        k_bar = conf.N__sc___RB_DL/2*(conf.N__ID___cell%2*conf.N__RB___DL)
        for n in range(4):
            k = k_bar + floor(n*conf.N__RB___DL/2)*conf.N__sc___RB_DL/2
            k___singleQuote = int(k/6)
            l___singleQuote = l
            reg = slot.rgs[0].reg(k___singleQuote, l___singleQuote)
            # reg = slot.rgs[0].regs[(k___singleQuote, l___singleQuote)]
            for re in reg().res:
                if re().t.typeName == 'crs':
                   continue
                else:
                    res.append(re)
                    re().p = 0
                    re().a = 0 #TODO: shall initialized with actual precoding result
                    re().t = ReType('pcfich')

        self.res = res
        self.patch, self.codes, self.vertices = self._initPatch()


    #TODO: 6.7.1 Scrambling
    #TODO: 6.7.2 Modulation
    #TODO: 6.7.3 Layer mapping and precoding
    def _initNumOfOfdmSymb4PDCCH(self, numOfOfdmSymb4PDCCH:int):
        """
        Tabel 6.7-1:Number of OFDM symbols used for PDCCH
        init and assert num of OFDM symbols for PDCCH based on cell configuration
        :param numOfOfdmSymb4PDCCH:
        :return:
        """

        print(conf.P_crs)
        if (self.n == 1 or self.n == 6) and conf.FrameStructureType.frameStructureTypeName == 'TDD':
            if conf.N__RB___DL > 10:
                assert (numOfOfdmSymb4PDCCH ==1 or numOfOfdmSymb4PDCCH ==2 )
                return numOfOfdmSymb4PDCCH
            else:
                return 2
        elif (self.subFrameType.subFrameTypeName != 'U') and (self.MBSFN == True) and (conf.N__ANT_PORTS <= 2):
            if conf.N__RB___DL > 10:
                assert (numOfOfdmSymb4PDCCH ==1 or numOfOfdmSymb4PDCCH ==2 )
                return numOfOfdmSymb4PDCCH
            else:
                return 2
        elif self.subFrameType.subFrameTypeName != 'U' and self.MBSFN == True and conf.N__ANT_PORTS == 4:
            return 2
        elif self.subFrameType.subFrameTypeName == 'U':
            return 0
        elif self.MBSFN == False and self.PRS == True and (self.n != 6 and conf.FrameStructureType.frameStructureTypeName == 'TDD'):
            if conf.N__RB___DL > 10:
                assert (numOfOfdmSymb4PDCCH == 1 or numOfOfdmSymb4PDCCH == 2 or  numOfOfdmSymb4PDCCH == 3 )
                return numOfOfdmSymb4PDCCH
            else:
                assert (numOfOfdmSymb4PDCCH == 2 or  numOfOfdmSymb4PDCCH == 3 )
                return numOfOfdmSymb4PDCCH
        else:
            if conf.N__RB___DL > 10:
                assert (numOfOfdmSymb4PDCCH == 1 or numOfOfdmSymb4PDCCH == 2 or  numOfOfdmSymb4PDCCH == 3 )
                return numOfOfdmSymb4PDCCH
            else:
                assert (numOfOfdmSymb4PDCCH == 2 or  numOfOfdmSymb4PDCCH == 3 or numOfOfdmSymb4PDCCH == 4)
                return numOfOfdmSymb4PDCCH

    def _initPatch(self):
        """
        deprecated!!!!
        get pathPatches for plotting res for CRS of dedicate port
        :return:
        """
        codes = []
        vertices = []
        for re in self.res:
            codes += re().codes
            vertices += re().vertices

        path = Path(vertices, codes)
        patch = PathPatch(path, facecolor='white', edgecolor='black', linewidth=0.2, fill='none')
        patch.set_zorder(90)
        return patch, codes, vertices