import csv
import math
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import gamma

PI = math.pi
T_h = 1
V_MAX = 5
S_th = 5
D_sth = 20
H_UAV = 200
P_T = 33 #dBm
ALPHA = 2.5

scale = 10 #  比例尺 每格对应距离

shape1 = 2.5
scale1 = 1.0

shape2 = 4
scale2 = 2

class UE:
    def __init__(self,loc):
        self.loc = loc
        self.sort = 1
        # self.snr = 0

def get_distance_2d(node1,node2):
    return ((node1[0] - node2[0]) ** 2 + (node1[1] - node2[1]) ** 2) ** 0.5

def read_UElist(ue_addr):
    ue_list = []
    with open(ue_addr, 'r') as f:
        f = csv.reader(f, delimiter=',')
        next(f)
        for row in f:
            ue_list.append(row)
    for i in range(len(ue_list)):
        ue_list[i] = list(map(int, ue_list[i]))
    return ue_list
# 两圆的重叠面积
def get_circle_overlap_area(node1, node2, r):
    x1, y1 = node1[0],node1[1]
    x2, y2 = node2[0],node2[1]
    if x1 == x2 and y1 == y2:return
    r1 = r
    r2 = r
    # 计算两个圆心之间的距离
    d = math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2)
    # 完全重叠的情况
    if d < abs(r2 - r1):
        return min(math.pi * r1 ** 2, math.pi * r2 ** 2)
    # 不相交的情况
    if d > r1 + r2:
        return 0
    # 计算重叠部分的面积
    alpha = math.acos((r1 ** 2 + d ** 2 - r2 ** 2) / (2 * r1 * d))
    beta = math.acos((r2 ** 2 + d ** 2 - r1 ** 2) / (2 * r2 * d))
    area1 = 0.5 * alpha * r1 ** 2 - 0.5 * r1 ** 2 * math.sin(2 * alpha)
    area2 = 0.5 * beta * r2 ** 2 - 0.5 * r2 ** 2 * math.sin(2 * beta)
    overlap_area = area1 + area2

    return overlap_area

def get_prop_success(node1,node2,r):
    w_over = get_circle_overlap_area(node1,node2,r)

    sin_theta = (node2[1]-node1[1])/(node1[0]-node2[0]) if node2[0]!=node1[0] else 1
    D_h = V_MAX * T_h
    p = w_over/(PI*D_h*D_h+4*D_h*r*sin_theta)
    return p

def get_prop_fail(node1,node2,r):
    d_12 = get_distance_2d(node1,node2)
    if d_12 > 2*r:
        return 0
    p = 1 - math.atan(r*math.sin(math.acos(d_12/(2*r)))/D_sth)/PI
    return p

def pathlossA2G(dist2,h=0):
    f = 1.4e9  # MHz
    d0 = 1
    c = 3e8
    alpha = 3.5
    pi = math.pi
    A = 0.25
    C = 0.39
    E = 0.25
    G = 0
    H = 0.05
    dep_tree = 2  # 植被深度
    dist3d = math.sqrt((dist2*100)**2 + h**2)
    fspl = 20 * np.log10(4 * pi * f * d0 / c) + 10 * alpha * math.log10(dist3d / d0)
    theta = math.atan2(h, dist2*100)
    slant =  A * np.power(f / math.pow(10, 6), C) * np.power(dep_tree, E) * np.power(theta + G, H)
    return fspl + slant

def getPathLoss(node1,node2):
    distance2d = get_distance_2d(node1, node2)
    pl = pathlossA2G(distance2d, H_UAV)
    return pl
def get_gaussian_random(mean=0, std=6, size=1):
    np.random.seed(0)
    gaussian_random = np.random.normal(mean, std, size)
    return gaussian_random[0]

def get_rss(node1,node2):
    pl = getPathLoss(node1,node2)
    dis = get_distance_2d(node1,node2)
    d_0 = 1
    if dis == 0:
        rss = P_T - pl + get_gaussian_random()
    else:   # 距离 -- 比例尺
        rss = P_T - pl - 10 * ALPHA * np.log10(dis*scale/ d_0) + get_gaussian_random()
    # rss = P_T - pl - 10*ALPHA*np.log10(dis/d_0) + get_gaussian_random()
    return rss

def calculate_gamma_pdf(x, demand_type):
    if demand_type == 1:
        pdf_value = gamma.pdf(x, shape1, scale1)
    elif demand_type == 2:
        pdf_value = gamma.pdf(x, shape2, scale2)
    else:
        raise ValueError("Invalid demand type")

    return pdf_value

def calculate_gamma_cdf(x, demand_type):
    if demand_type == 1:
        cdf_value = gamma.cdf(x, shape1, scale1)
    elif demand_type == 2:
        cdf_value = gamma.cdf(x, shape2, scale2)
    else:
        raise ValueError("Invalid demand type")

    return cdf_value

def random_walk_2D(ue_list, n_steps):
    n_ue = len(ue_list)  # 用户数量
    # 初始化位置数组
    positions = np.zeros((n_ue, n_steps, 2))
    step_size = 0.5   # 0.05: 12.5m/s 低速； 0.15 25m/s 中速; 0.25 37.5m/s 高速
    for i in range(n_ue):
        # 生成随机步长数组，每一步步长为 (-1,-1), (-1,0), (-1,1), (0,-1), (0,0), (0,1), (1,-1), (1,0), (1,1)
        steps = np.random.uniform(low=-1*step_size, high=step_size, size=(n_steps, 2))
        # 0.01m每毫秒 11m/s 20km/h
        # 计算每一步的位置
        positions[i, :, :] = ue_list[i] + np.cumsum(steps, axis=0)
    # for step_index in range(n_steps):
    #     show_ue(positions[:, step_index, :])
    return positions

def get_ue_sort(ue_idx):
    r1 = calculate_gamma_pdf(ue_idx, 1)
    r2 = calculate_gamma_pdf(ue_idx, 2)

    return  1 if r1 > r2 else 2
def get_x_step_position(positions,step_index):
    UE_list = []
    ue_list = positions[:, step_index, :]
    for i in range(len(ue_list)):
        ue = UE(ue_list[i])
        ue.sort = get_ue_sort(i)
        UE_list.append(ue)
    return UE_list

def show_ue(ue_list):
    # 模拟二维随机游走
    # 绘制每一步的用户位置
    plt.figure()

    x = ue_list[:, 0]
    y = ue_list[:, 1]
    plt.scatter(x, y)

if __name__ == '__main__':
    node1 = [0,0]
    node2 = [10,10]
    r = 10
    # print(get_prop_success(node1,node2,r),get_prop_fail(node1,node2,r))
    # print(get_rss(node1,node2))
    x = 2.0
    demand_type = 1
    pdf = calculate_gamma_pdf(x, demand_type)
    cdf = calculate_gamma_cdf(x, demand_type)

    print("PDF:", pdf)
    print("CDF:", cdf)
    for i in range(30):
        r1 = calculate_gamma_pdf(i,1)
        r2 = calculate_gamma_pdf(i,2)
        print(i,r1<r2)


