# -*- coding: utf-8 -*-

import math
import random
import hashlib
import numpy as np

def OUEParams(epsilon):
    """计算OUE法扰动概率"""
    # epsilon 隐私预算
    
    temp_data=math.pow(math.e,epsilon)
    prob_p1 =0.5
    prob_q1 =0.5
    prob_p2 = float(temp_data)/(temp_data+1)
    prob_q2 = 1.0/(temp_data+1)
    
    return [prob_p1,prob_q1,prob_p2,prob_q2]

def JudgeLocation(single_user_data,layer_node_range):
    """判断用户数据在树中某一层的位置"""
    # single_user_data 单个用户数据，形式为['x','y']
    # layer_node_range 四分树某一层各结点范围，形式为[[],[],[]]
    
    for i in xrange(len(layer_node_range)) :
        temp1=layer_node_range[i][0]
        temp2=layer_node_range[i][1]
        temp3=layer_node_range[i][2]
        temp4=layer_node_range[i][3]
        if temp1<=float(single_user_data[0])<temp2 and temp3<=float(single_user_data[1])<temp4:
            return i

def SingleDataEncode(single_user_data,range_list,layer_number):
    """对单个用户数据进行编码"""
    # single_user_data 单个用户数据，形式为['x','y']
    # range_list 四分树各层结点范围
    # layer_number 四分树的高度
    
    random_number=random.randint(0,layer_number-1) # 随机选择树的一层
    layer_node_number=math.pow(4,random_number)
    encode_single_user_data=[0 for _ in xrange(layer_node_number)]
    
    if random_number==0:
        encode_single_user_data=[1]
    else:
        temp_index=JudgeLocation(single_user_data,range_list[random_number])
        encode_single_user_data[temp_index]=1
    
    return encode_single_user_data

def SingleDataDisturb(encode_single_user_data,oue_params):
    """扰动单个用户数据"""
    # encode_single_user_data 单个用户数据编码
    # oue_params OUE法扰动概率
    
    prob_p1=oue_params[0]
    prob_p2=oue_params[2]
    temp_length=len(encode_single_user_data)
    noise_single_user_data=[0 for _ in xrange(temp_length)]
    
    for i in xrange(temp_length):
        temp_number=random.random()
        if encode_single_user_data[i]==0:
            if temp_number < prob_p2: 
                noise_single_user_data[i]=0
            else:
                noise_single_user_data[i]=1
        else:
            if temp_number < prob_p1: 
                noise_single_user_data[i]=1
            else:
                noise_single_user_data[i]=0
    
    return noise_single_user_data
    
def OueAllDataDisturb(all_user_data,range_list,layer_number,oue_params):
    """扰动所有用户数据"""
    # all_user_data 所有用户数据列表
    # range_list 四分树各层结点范围
    # layer_number 四分树的高度
    # oue_params OUE法扰动概率
    
    noise_all_user_data=[]
    
    for i in all_user_data:
        encode_single_user_data=SingleDataEncode(i,range_list,layer_number)
        noise_single_user_data=SingleDataDisturb(encode_single_user_data,oue_params)
        noise_all_user_data.append(noise_single_user_data)
    
    return noise_all_user_data




