import requests
import json
import os
import hashlib
from requests.auth import HTTPDigestAuth
import time
import datetime
#import cv2
import base64
import numpy as np

username="admin"
password="admin"
face_db_name='RD'

# base 64 圖片 轉換
def cv2_base64(image):
    base64_str = cv2.imencode('.jpg',image)[1].tostring()
    base64_str = base64.b64encode(base64_str)
    return base64_str

def base64_cv2(base64_str):
    imgString = base64.b64decode(base64_str)
    nparr = np.fromstring(imgString,np.uint8)  
    image = cv2.imdecode(nparr,cv2.IMREAD_COLOR)
    return image

# 產生 RFC 2617 response header
def RFC2617_response_header(username,password,h,method,uri):
    realm=h.split("Digest realm=")[1].split(',')[0].strip('"')
    nonce=h.split("nonce=")[1].split(',')[0].strip('"')
    ha1_md5 = hashlib.md5()
    
    ha1_md5.update("{}:{}:{}".format(username,realm,password).encode("utf-8"))
    HA1=ha1_md5.hexdigest().upper()

    ha2_md5 = hashlib.md5()
    ha2_md5.update("{}:{}".format(method,uri).encode("utf-8"))
    HA2=ha2_md5.hexdigest().upper()

    response_md5 = hashlib.md5()
    response_md5.update("{}:{}:{}".format(HA1,nonce,HA2).encode("utf-8"))
    response_digest=response_md5.hexdigest().upper()
    
    headers = {
    "Authorization": '''Digest username="{}", realm="{}", nonce="{}",uri="{}", response="{}", opaque=""'''.format(username,realm,nonce,uri,response_digest),
    "Cache-Control": "no-cache"
    }
    
    return headers

def get_person_lib(camera_path):
    method="GET"
    uri="/LAPI/V1.0/PeopleLibraries/BasicInfo"
    response=requests.get(camera_path+uri)
    if(response.status_code==401):
        # 驗證過期
        # 重新計算憑證
        headers=RFC2617_response_header(username,password,response.headers['WWW-Authenticate'],method,uri)
        r=requests.get(camera_path+uri,headers=headers,auth=HTTPDigestAuth(username, password))
        # 驗證成功
    json_response=json.loads(r.content.decode("utf-8"))
    return json_response["Response"]["Data"]["LibList"]
def delete_person_lib(camera_path,uid):
    method="DELETE"
    uri="/LAPI/V1.0/PeopleLibraries/"+str(uid)
    response=requests.get(camera_path+uri)

    if(response.status_code==401):
        # 驗證過期
        # 重新計算憑證
        headers=RFC2617_response_header(username,password,response.headers['WWW-Authenticate'],method,uri)
        r=requests.delete(camera_path+uri,headers=headers,auth=HTTPDigestAuth(username, password))
    # 驗證成功
    json_response=json.loads(r.content.decode("utf-8"))
    if(json_response["Response"]["StatusString"] == "Succeed"):
        return True
    else:
        return False
def create_person_lib(camera_path):
    method="POST"
    uri="/LAPI/V1.0/PeopleLibraries/BasicInfo"
    response=requests.get(camera_path+uri)

    dtime = datetime.datetime.now()
    ans_time = time.mktime(dtime.timetuple())

    json_request={
    "Name":face_db_name, # 人臉庫名稱
    "Type":3, # 人臉庫類型，0 -> 預設無效值，1 -> 黑名單，2 -> 灰名單/陌生人，3 -> 員工，4 -> 訪客
    "PersonNum":0, # 人臉庫總人數，有多少個不同的PersonID
    "FaceNum":0, # 人臉庫人臉照片總數，有多少張人臉照片或特徵
    "MemberNum":0, # 庫中人員成員總數，有多少個不同的FaceID
    "LastChange":int(ans_time), # 最後修改時間，Unix時間戳記
    "BelongIndex":face_db_name, # 人臉庫的索引，用來標示此人臉庫屬於哪個設備
    # "IsMonitored":0 # 是否已啟用布控，GET方法時必帶，僅VMS支援，0 -> 未布控，1 -> 已布控
    }
    if(response.status_code==401):
        # 驗證過期
        # 重新計算憑證
        headers=RFC2617_response_header(username,password,response.headers['WWW-Authenticate'],method,uri)
        headers['Content-type']='application/json'
        headers['Accept']='text/plain'
        r=requests.post(camera_path+uri,headers=headers,auth=HTTPDigestAuth(username, password),json=json_request)
     # 驗證成功
    json_response=json.loads(r.content.decode("utf-8"))
    if(json_response["Response"]["StatusString"] == "Succeed"):
        return json_response["Response"]["ID"]
    else:
        return None
def insert_face(camera_path,person_id,gender,face_path):
    # 獲取人臉庫編號
    db_id=None
    for lib in get_person_lib(camera_path):
#         print(lib["ID"])
        if(lib["Name"] == face_db_name):
            db_id=lib["ID"]
        else:
            delete_person_lib(camera_path,lib["ID"])
    if(db_id is None):
        # 未存在相對應 -> 新增一個
#         print("create new db")
        db_id=create_person_lib(camera_path)
    if(db_id is None):
        return False
    # 轉換成base64img
    img=cv2.imread(face_path)
    base64img=cv2_base64(img).decode('utf-8')
    # 上傳人臉
    method = "POST"

    dtime = datetime.datetime.now()
    ans_time = time.mktime(dtime.timetuple())

    uri="/LAPI/V1.0/PeopleLibraries/{}/People".format(db_id)
    response=requests.get(camera_path+uri)
    json_request={
        "Num": 1, # 新增人員各數
        "PersonInfoList":[
            {
            "PersonID":0, # 人員編號，如果為 0，則由設備自行編號
            "LastChange":int(ans_time), # 最後一次修改時間，Unix時間戳記
            "PersonName":person_id, # 人員姓名
            "Gender":1, # 性別， 0 -> 未知， 1 -> 男性， 2 -> 女性 ， 9 -> 未說明
            "Birthday":"", # 生日，格式 YYYYMMDD
            "Region": { # 地區訊息
                        "Nation":"",
                        "Province":"",
                        "City":""
                        },
    #         "TimeTemplateNum":1, # 時間參數個數
    #         "TimeTemplateList":[ { 
    #                     "BeginTime":30980472,
    #                     "EndTime":30955816,
    #                     "Index":30987352
    #                     }],
    #         "IdentificationNum":1, # 證件訊息個數
    #         "IdentificationList": [{
    #                 "Type":27714208,
    #                 "Number":""
    #         }],
            "ImageNum":1, # 人臉圖片個數
            "ImageList":[{ # 人臉圖片訊息列表
                "FaceID":0, # 人臉照片ID
                "ModelStatus":0, # 建模狀態，0 -> 未建模， 1 -> 已建模 ， 2 -> 建模失敗
                "Name":"{}_1.jpg".format(person_id), 
                "Size":len(base64img),
                "Data":base64img
                }
            ]
            }
        ]
    }
    if(response.status_code==401):
        # 驗證過期
        # 重新計算憑證
        headers=RFC2617_response_header(username,password,response.headers['WWW-Authenticate'],method,uri)
        headers['Content-type']='application/json'
        headers['Accept']='text/plain'
        r=requests.post(camera_path+uri,headers=headers,json=json_request,auth=HTTPDigestAuth(username, password))
    json_response=json.loads(r.content.decode("utf-8"))
#     print(json_response)
    if(json_response["Response"]["StatusString"] == "Succeed"):
        return True
    else:
        return False
def get_id_by_name(camera_path,person_name):
    # 獲取人臉庫編號
    db_id=None
    for lib in get_person_lib(camera_path):
#         print(lib["ID"])
        if(lib["Name"] == face_db_name):
            db_id=lib["ID"]
        else:
            delete_person_lib(camera_path,lib["ID"])
    if(db_id is None):
        # 未存在相對應 -> 新增一個
#         print("create new db")
        db_id=create_person_lib(camera_path)
    if(db_id is None):
        return False
    
    # 搜尋相對應目標
    method="POST"
    uri="/LAPI/V1.0/PeopleLibraries/{}/People/Info".format(db_id)
    response=requests.get(camera_path+uri)
    json_request={
                "Num":1, # 查詢條件數量，Num多少，QueryInfos list的長度就多少
                "QueryInfos": [ # 搜尋條件，可包含多個搜尋條件
                    {
                   "QryType":55 , # 搜尋對象，0 -> 使用者名稱 ， 1 -> 組織名稱 ， 2 -> 設備名稱 ，3 -> 通道名稱 ， 4 -> 時間(UTC格式，秒)， 55 -> 人員姓名....
                    "QryCondition":0 , # 搜尋條件， 0 -> 等於， 1 -> 大於 ， 2 -> 小於 ， 3 -> 大於等於 ， 4 -> 小於等於 ， 5 -> 不等於 ， 6 -> 模糊搜尋 ， 7 -> IN集合 ， 8 -> 升冪排序， 9 -> 降冪排序
                    "QryData":person_name # 搜尋值
                    }
                ],
                "Limit":20 ,
                "Offset":0
    }
    if(response.status_code==401):
        # 驗證過期
        # 重新計算憑證
        headers=RFC2617_response_header(username,password,response.headers['WWW-Authenticate'],method,uri)
        headers['Content-type']='application/json'
        headers['Accept']='text/plain'
        r=requests.post(camera_path+uri,headers=headers,json=json_request,auth=HTTPDigestAuth(username, password))
    json_response=json.loads(r.content.decode("utf-8"))
    if(json_response["Response"]["StatusString"] == "Succeed"):
        return json_response["Response"]["Data"]["PersonList"]["PersonInfoList"]
    else:
        return []
def delete_person(camera_path,name):
    # 獲取人臉庫編號
    db_id=None
    for lib in get_person_lib(camera_path):
#         print(lib["ID"])
        if(lib["Name"] == face_db_name):
            db_id=lib["ID"]
        else:
            delete_person_lib(camera_path,lib["ID"])
    if(db_id is None):
        # 未存在相對應 -> 新增一個
#         print("create new db")
        db_id=create_person_lib(camera_path)
    if(db_id is None):
        return False
    # 獲取人臉清單
    person_list = get_id_by_name(camera_path,name)
    person_id=None
    if(len(person_list)>=1):
        person_id=person_list[0]["PersonID"]
    else:
        return True
    method="DELETE"
    uri="/LAPI/V1.0/PeopleLibraries/{}/People/{}".format(db_id,person_id)
    response=requests.get(camera_path+uri)

    if(response.status_code==401):
        # 驗證過期
        # 重新計算憑證
        headers=RFC2617_response_header(username,password,response.headers['WWW-Authenticate'],method,uri)
        r=requests.delete(camera_path+uri,headers=headers,auth=HTTPDigestAuth(username, password))
    json_response=json.loads(r.content.decode("utf-8"))
#     print(json_response)
    if(json_response["Response"]["StatusString"] == "Succeed"):
        return True
    else:
        return False