from passlib.hash import pbkdf2_sha256 as sha256
from datetime import datetime
from io import BytesIO
from PIL import Image
from dbsql import MySQL
#from mtcnn import MTCNN
from matplotlib import pyplot as plt
import os, json, base64, requests
from CM26EWH_model import insert_face,delete_person

env = os.environ
host = env['MYSQL_HOST']      if 'MYSQL_HOST' in env else "192.168.6.194"
port = int(env['MYSQL_PORT']) if 'MYSQL_PORT' in env else 23306
usr  = env['MYSQL_USR']       if 'MYSQL_USR'  in env else "root"
pwd  = env['MYSQL_PWD']       if 'MYSQL_PWD'  in env else "123456"
db   = env['MYSQL_DB']        if 'MYSQL_DB'   in env else "ecom"
mysql = MySQL(host, port, usr, pwd, db)
#detector = MTCNN()

print(host, port)

# ===== 基礎資料庫模型 =====
class BaseModel(object):
    def __init__(self):
        self.data = { 'created': self.GetNow(), 'updated': self.GetNow(), }
        self.change = {}
        self.isExist = False
    def IsEnabled(self):
        return self.GetDeleted() is None
    def SetCreated(self, created=None):
        self.data['created'] = self.GetNow() if created is None else created
    def SetUpdated(self, updated=None):
        self.data['updated'] = self.GetNow() if updated is None else updated
    def SetDeleted(self, deleted=None):
        self.data['deleted'] = deleted
    def SetValue(self, key, value, valueType, canNull):
        if value is not None or canNull:
            value1 = value if isinstance(value, valueType) or canNull else valueType(value)
            if key in self.data and self.data[key] is not None:
                value2 = self.data[key] if isinstance(self.data[key], valueType) else valueType(self.data[key])
                if value1 != value2:
                    self.change[key] = self.data[key]
            self.data[key] = value1
            self.SetUpdated()
            return True
        return False
    def GetCreated(self):
        return self.StringToDatetime(self.data['created']) if 'created' in self.data and self.data['created'] is not None else None
    def GetUpdated(self):
        return self.StringToDatetime(self.data['updated']) if 'updated' in self.data and self.data['updated'] is not None else None
    def GetDeleted(self):
        return self.StringToDatetime(self.data['deleted']) if 'deleted' in self.data and self.data['deleted'] is not None else None
    def GetHash(self, password):
        return "" if password is None or len(password) == 0 else sha256.hash(password)
    def GetNow(self):
        return self.DatetimeToString(datetime.now())
    def DatetimeToString(self, _datetime):
        if isinstance(_datetime, datetime):
            return "{0}{1}".format(_datetime.year - 1911, _datetime.strftime('%m%d%H%M%S'))
        else:
            return None
    def StringToDatetime(self, _string):
        if isinstance(_string, str) and len(_string) == 13:
            y = int(_string[0:3]) + 1911
            _datetime = datetime.strptime(_string[3:13], "%m%d%H%M%S")
            _datetime = _datetime.replace(y)
            return _datetime
        else:
            return None
# ===== 使用者資料庫模型 =====
class UserModel(BaseModel):
    def __init__(self, ID):
        super().__init__()
        self.table = 'user'
        self.data['id'] = ID
        self.data['person_id'] = None
        self.data['name'] = None
        self.data['department'] = None
        self.data['on_board'] = None
        self.data['username'] = None
        self.data['password'] = None
        self.data['email'] = None
    # ===== person_id ========================================
    def SetPersonId(self, person_id):
        return self.SetValue('person_id', person_id, str, False)
    def GetPersonId(self):
        return self.data['person_id'] if 'person_id' in self.data else None
    def GetOldPersonId(self):
        return self.change['person_id']
    def HasChangePersonId(self):
        return 'person_id' in self.change
    # ===== name ========================================
    def SetName(self, name):
        return self.SetValue('name', name, str, False)
    def GetName(self):
        return self.data['name'] if 'name' in self.data else None
    def GetOldName(self):
        return self.change['name']
    def HasChangeName(self):
        return 'name' in self.change
    # ===== department ========================================
    def SetDepartment(self, department):
        return self.SetValue('department', department, str, False)
    def GetDepartment(self):
        return self.data['department'] if 'department' in self.data else None
    def GetOldDepartment(self):
        return self.change['department']
    def HasChangeDepartment(self):
        return 'department' in self.change
    # ===== role ========================================
    def SetRole(self, role):
        return self.SetValue('role', role, int, True)
    def GetRole(self):
        return self.data['role'] if 'role' in self.data else None
    def GetOldRole(self):
        return self.change['role']
    def HasChangeRole(self):
        return 'role' in self.change
    # ===== on_board ========================================
    def SetOnBoard(self, on_board):
        return self.SetValue('on_board', on_board, str, True)
    def GetOnBoard(self):
        return self.data['on_board'] if 'on_board' in self.data else None
    def GetOldOnBoard(self):
        return self.change['on_board']
    def HasChangeOnBoard(self):
        return 'on_board' in self.change
    # ===== username ========================================
    def SetUsername(self, username):
        return self.SetValue('username', username, str, False)
    def GetUsername(self):
        return self.data['username'] if 'username' in self.data else None
    def GetOldUsername(self):
        return self.change['username']
    def HasChangeUsername(self):
        return 'username' in self.change
    # ===== password ========================================
    def SetPassword(self, password):
        return self.SetValue('password', self.GetHash(password), str, False)
    def GetPassword(self):
        return self.data['password'] if 'password' in self.data else None
    def GetOldPassword(self):
        return self.change['password']
    def HasChangePassword(self):
        return 'password' in self.change
    # ===== email ========================================
    def SetEmail(self, email):
        return self.SetValue('email', email, str, True)
    def GetEmail(self):
        return self.data['email'] if 'email' in self.data else None
    def GetOldEmail(self):
        return self.change['email']
    def HasChangeEmail(self):
        return 'email' in self.change
    # ===== operate database ========================================
    def InsertToDB(self):
        keys = self.data.keys()
        values = [ self.data[x] for x in keys ]
        script = mysql.Insert(self.table, keys, values)
        return script.Fetch()
    def UpdateToDB(self):
        script = None
        for k in self.data.keys():
            if(k!="password"):
                script = mysql.Update(self.table, k, self.data[k]) if script is None else script.Add(k, self.data[k])
        script = script.Where('id', '=', self.data['id'])
        return script.FetchOne()
    def UpdateToDBForPassword(self):
        script = None
        for k in self.data.keys():
            script = mysql.Update(self.table, k, self.data[k]) if script is None else script.Add(k, self.data[k])
        script = script.Where('id', '=', self.data['id'])
        return script.FetchOne()
    def DeleteFromDB(self):
        script = mysql.Delete(self.table).Where('id', '=', self.data['id'])
        return script.FetchOne()
    # ===== other ========================================
    @staticmethod
    def FromDB(ID, log):
        model = UserModel(ID)
        mysql.SetLog(log)
        script = mysql.Select('user').Where('id', '=', ID).FetchOne()
        if isinstance(script, tuple):
            model.SetPersonId(script[1])
            model.SetName(script[2])
            model.SetDepartment(script[3])
            model.SetRole(script[4])
            model.SetOnBoard(script[5])
            model.SetUsername(script[6])
            model.SetPassword(script[7])
            model.SetEmail(script[8])
            model.SetCreated(script[9])
            model.SetUpdated(script[10])
            model.SetDeleted(script[11])
            model.isExist = True
        return model
    @staticmethod
    def SelectAllFromDB():
        script = mysql.Select('user')
        return script.FetchAll()
# ===== 使用者資料庫驗證模型 =====
class UserAuthModel(BaseModel):
    def __init__(self,username,authpassword):
        super().__init__()
        self.table = 'user'
        self.data['id'] = None
        self.data['person_id'] = None
        self.data['name'] = None
        self.data['department'] = None
        self.data['on_board'] = None
        self.data['username'] = username
        self.data['authpassword']=authpassword
        self.data['password'] = None
        self.data['email'] = None
        self.isauthed = False
    # ===== id ========================================
    def SetId(self, uid):
        return self.SetValue('id', uid, str, False)
    def GetId(self):
        return self.data['id'] if 'id' in self.data else None
    # ===== person_id ========================================
    def SetPersonId(self, person_id):
        return self.SetValue('person_id', person_id, str, False)
    def GetPersonId(self):
        return self.data['person_id'] if 'person_id' in self.data else None
    def GetOldPersonId(self):
        return self.change['person_id']
    def HasChangePersonId(self):
        return 'person_id' in self.change
    # ===== name ========================================
    def SetName(self, name):
        return self.SetValue('name', name, str, False)
    def GetName(self):
        return self.data['name'] if 'name' in self.data else None
    def GetOldName(self):
        return self.change['name']
    def HasChangeName(self):
        return 'name' in self.change
    # ===== department ========================================
    def SetDepartment(self, department):
        return self.SetValue('department', department, str, False)
    def GetDepartment(self):
        return self.data['department'] if 'department' in self.data else None
    def GetOldDepartment(self):
        return self.change['department']
    def HasChangeDepartment(self):
        return 'department' in self.change
    # ===== role ========================================
    def SetRole(self, role):
        return self.SetValue('role', role, int, True)
    def GetRole(self):
        return self.data['role'] if 'role' in self.data else None
    def GetOldRole(self):
        return self.change['role']
    def HasChangeRole(self):
        return 'role' in self.change
    # ===== on_board ========================================
    def SetOnBoard(self, on_board):
        return self.SetValue('on_board', on_board, str, True)
    def GetOnBoard(self):
        return self.data['on_board'] if 'on_board' in self.data else None
    def GetOldOnBoard(self):
        return self.change['on_board']
    def HasChangeOnBoard(self):
        return 'on_board' in self.change
    # ===== username ========================================
    def SetUsername(self, username):
        return self.SetValue('username', username, str, False)
    def GetUsername(self):
        return self.data['username'] if 'username' in self.data else None
    def GetOldUsername(self):
        return self.change['username']
    def HasChangeUsername(self):
        return 'username' in self.change
    # ===== password ========================================
    def SetPassword(self, password):
        return self.SetValue('password', password, str, False)
    def GetPassword(self):
        return self.data['password'] if 'password' in self.data else None
    def SetAuthPassword(self, authpassword):
        return self.SetValue('authpassword', authpassword, str, False)
    def GetAuthPassword(self):
        return self.data['authpassword'] if 'authpassword' in self.data else None
    def GetOldPassword(self):
        return self.change['password']
    def HasChangePassword(self):
        return 'password' in self.change
    def PasswordAuth(self):
        return sha256.verify(self.GetAuthPassword(),self.GetPassword())
    # ===== email ========================================
    def SetEmail(self, email):
        return self.SetValue('email', self.GetHash(email), str, False)
    def GetEmail(self):
        return self.data['email'] if 'email' in self.data else None
    def GetOldEmail(self):
        return self.change['email']
    def HasChangeEmail(self):
        return 'email' in self.change
    # ===== other ========================================
    @staticmethod
    def FromDB(username,password, log):
        model = UserAuthModel(username,password)
        mysql.SetLog(log)
        script = mysql.Select('user').Where('username', '=', username).FetchOne()
        if isinstance(script, tuple):
            model.SetId(script[0])
            model.SetPersonId(script[1])
            model.SetName(script[2])
            model.SetDepartment(script[3])
            model.SetRole(script[4])
            model.SetOnBoard(script[5])
            model.SetUsername(script[6])
            model.SetPassword(script[7])
            model.SetEmail(script[8])
            model.SetCreated(script[9])
            model.SetUpdated(script[10])
            model.SetDeleted(script[11])
            model.isExist = True
            model.isauthed=model.PasswordAuth()
        return model
# ===== 使用者角色資料庫模型 =====
class UserRoleModel(BaseModel):
    def __init__(self, ID=None):
        super().__init__()
        self.table = 'user_role'
        if ID is not None:
            self.data['id'] = ID
        self.data['name'] = None
    # ===== id ========================================
    def SetID(self, ID):
        return self.SetValue('id', ID, str, False)
    # ===== name ========================================
    def SetName(self, name):
        return self.SetValue('name', name, str, False)
    def GetName(self):
        return self.data['name'] if 'name' in self.data else None
    def GetOldName(self):
        return self.change['name']
    def HasChangeName(self):
        return 'name' in self.change
    # ===== operate database ========================================
    def InsertToDB(self, log):
        keys = self.data.keys()
        values = [ self.data[x] for x in keys ]
        mysql.SetLog(log)
        script = mysql.Insert(self.table, keys, values)
        return script.Fetch()
    def UpdateToDB(self, log):
        script = None
        for k in self.data.keys():
            mysql.SetLog(log)
            script = mysql.Update(self.table, k, self.data[k]) if script is None else script.Add(k, self.data[k])
        script = script.Where('id', '=', self.data['id'])
        return script.FetchOne()
    def DeleteFromDB(self, log):
        mysql.SetLog(log)
        script = mysql.Delete(self.table).Where('id', '=', self.data['id'])
        return script.FetchOne()
    # ===== other ========================================
    @staticmethod
    def FromDB(ID, log):
        model = UserRoleModel(ID)
        mysql.SetLog(log)
        script = mysql.Select('user_role').Where('id', '=', ID).FetchOne()
        if isinstance(script, tuple):
            model.SetName(script[1])
            model.isExist = True
        return model
    @staticmethod
    def FromName(name, log):
        model = UserRoleModel()
        mysql.SetLog(log)
        script = mysql.Select('user_role').Where('name', '=', name).FetchOne()
        if isinstance(script, tuple):
            model.SetID(script[0])
            model.SetName(script[1])
            model.SetCreated(script[2])
            model.SetUpdated(script[3])
            model.SetDeleted(script[4])
            model.isExist = True
        return model
    @staticmethod
    def SelectAllFromDB(log):
        script = mysql.Select('user_role')
        return script.FetchAll()
# ===== person data model =====
class PersonModel(BaseModel):
    def __init__(self, ID):
        super().__init__()
        self.table = 'person'
        self.data['id'] = ID
        self.data['name'] = None
        self.data['sex'] = None
        self.data['type'] = None
        self.data['photo'] = None
    # ===== id ========================================
    def GetID(self):
        return self.data['id'] if 'id' in self.data else None
    # ===== name ========================================
    def SetName(self, name):
        return self.SetValue('name', name, str, False)
    def GetName(self):
        return self.data['name'] if 'name' in self.data else None
    def GetOldName(self):
        return self.change['name']
    def HasChangeName(self):
        return 'name' in self.change
    # ===== sex ========================================
    def SetSex(self, sex):
        return self.SetValue('sex', sex, int, False)
    def GetSex(self):
        return self.data['sex'] if 'sex' in self.data else None
    def GetOldSex(self):
        return self.change['sex']
    def HasChangeSex(self):
        return 'sex' in self.change
    # ===== type ========================================
    def SetType(self, personType):
        return self.SetValue('type', personType, int, False)
    def GetType(self):
        return self.data['type'] if 'type' in self.data else None
    def GetOldType(self):
        return self.change['type']
    def HasChangeType(self):
        return 'type' in self.change
    # ===== token ========================================
    def SetToken(self, token):
        return self.SetValue('token', token, str, True)
    def GetToken(self):
        return self.data['token'] if 'token' in self.data else None
    def GetOldToken(self):
        return self.change['token']
    def HasChangeToken(self):
        return 'token' in self.change
    def HasToken(self):
        return 'token' in self.data and self.data['token'] is not None and len(self.data['token']) > 0
    # ===== photo ========================================
    def SetPhoto(self, photo):
        if isinstance(photo, str) and os.path.isfile(photo):
            buffer = BytesIO()
            image = plt.imread(photo)
            #faces = detector.detect_faces(image)
            faces = []
            if len(faces) > 0:
                height, width, dimension = image.shape
                # trim image to square
                x, y, w, h = faces[0]['box']
                cx = int(x + w / 2)
                cy = int(y + h / 2)
                z = min(cx, cy, width - cx, height - cy)
                z = 480 if z > 480 else z
                image = image[cy-z:cy+z, cx-z:cx+z]
                image = Image.fromarray(image)
            else:
                image = Image.fromarray(image)
                w, h = image.size
                z = w if w > h else h
                z = 960 / z if z > 960 else 1
                w = int(w * z)
                h = int(h * z)
                image = image.resize((w, h))
            image.save(buffer, format='JPEG')
            # convert image to base64 string
            photo = buffer.getvalue()
            photo = base64.b64encode(photo)
            photo = photo.decode('utf-8')
        return self.SetValue('photo', photo, str, False)
    def GetPhoto(self):
        return self.data['photo'] if 'photo' in self.data else None
    # ===== start ========================================
    def SetStart(self, start):
        try:
            start = start if isinstance(start, datetime) else datetime.strptime(start, "%Y-%m-%d %H:%M:%S")
            return self.SetValue('start', self.DatetimeToString(start), str, True)
        except:
            return start is None or len(start) == 0
    def GetStart(self):
        return self.StringToDatetime(self.data['start']) if 'start' in self.data else None
    def GetOldStart(self):
        return self.change['start']
    def HasChangeStart(self):
        return 'start' in self.change
    # ===== end ========================================
    def SetEnd(self, end):
        try:
            end = end if isinstance(end, datetime) else datetime.strptime(end, "%Y-%m-%d %H:%M:%S")
            return self.SetValue('end', self.DatetimeToString(end), str, True)
        except:
            return end is None or len(end) == 0
        return self.SetValue('end', self.DatetimeToString(end), str, True)
    def GetEnd(self):
        return self.StringToDatetime(self.data['end']) if 'end' in self.data else None
    def GetOldEnd(self):
        return self.change['end']
    def HasChangeEnd(self):
        return 'end' in self.change
    # ===== operate database ========================================
    def InsertToDB(self, log=None):
        keys = self.data.keys()
        values = [ self.data[x] for x in keys ]
        mysql.SetLog(log)
        script = mysql.Insert(self.table, keys, values)
        return script.Fetch()
    def UpdateToDB(self, log):
        script = None
        for k in self.data.keys():
            mysql.SetLog(log)
            script = mysql.Update(self.table, k, self.data[k]) if script is None else script.Add(k, self.data[k])
        script = script.Where('id', '=', self.data['id'])
        return script.FetchOne()
    def DeleteFromDB(self, log):
        script = mysql.Delete(self.table).Where('id', '=', self.data['id'])
        mysql.SetLog(log)
        return script.FetchOne()
    # ===== other ========================================
    @staticmethod
    def FromDB(ID, log):
        model = PersonModel(ID)
        mysql.SetLog(log)
        script = mysql.Select('person').Where('id', '=', ID).FetchOne()
        if isinstance(script, tuple):
            model.SetName(script[2])
            model.SetSex(script[3])
            model.SetType(script[4])
            model.SetToken(script[5])
            model.SetPhoto(script[6])
            model.SetStart(model.StringToDatetime(script[7]))
            model.SetEnd(model.StringToDatetime(script[8]))
            model.SetCreated(script[9])
            model.SetUpdated(script[10])
            model.SetDeleted(script[11])
            model.isExist = True
        return model
    @staticmethod
    def AllFromDB(log):
        models = []
        mysql.SetLog(log)
        script = mysql.Select('person').FetchAll()
        if isinstance(script, tuple):
            for row in script:
                model = PersonModel(row[1])
                model.SetName(row[2])
                model.SetSex(row[3])
                model.SetType(row[4])
                model.SetToken(row[5])
                model.SetPhoto(row[6])
                model.SetStart(model.StringToDatetime(row[7]))
                model.SetEnd(model.StringToDatetime(row[8]))
                model.SetCreated(row[9])
                model.SetUpdated(row[10])
                model.SetDeleted(row[11])
                model.isExist = True
                models.append(model)
        return models
# ===== person type data model =====
class PersonTypeModel(BaseModel):
    def __init__(self, ID=None):
        super().__init__()
        self.table = 'person_type'
        if ID is not None:
            self.data['id'] = ID
        self.data['name'] = None
    # ===== id ========================================
    def SetID(self, ID):
        return self.SetValue('id', ID, int, False)
    # ===== name ========================================
    def SetName(self, name):
        return self.SetValue('name', name, str, False)
    def GetName(self):
        return self.StringToDatetime(self.data['name']) if 'name' in self.data else None
    def GetOldName(self):
        return self.change['name']
    def HasChangeName(self):
        return 'name' in self.change
    # ===== operate database ========================================
    def InsertToDB(self, log):
        keys = self.data.keys()
        values = [ self.data[x] for x in keys ]
        mysql.SetLog(log)
        script = mysql.Insert(self.table, keys, values)
        return script.Fetch()
    def UpdateToDB(self, log):
        script = None
        for k in self.data.keys():
            mysql.SetLog(log)
            script = mysql.Update(self.table, k, self.data[k]) if script is None else script.Add(k, self.data[k])
        script = script.Where('id', '=', self.data['id'])
        return script.FetchOne()
    def DeleteFromDB(self, log):
        mysql.SetLog(log)
        script = mysql.Delete(self.table).Where('id', '=', self.data['id'])
        return script.FetchOne()
    @staticmethod
    def FromDB(ID, log):
        model = PersonTypeModel(ID)
        mysql.SetLog(log)
        script = mysql.Select('person_type').Where('id', '=', ID).FetchOne()
        if isinstance(script, tuple):
            model.SetName(script[1])
            model.isExist = True
        return model
    @staticmethod
    def FromName(name, log):
        model = PersonTypeModel()
        mysql.SetLog(log)
        script = mysql.Select('person_type').Where('name', '=', name).FetchOne()
        if isinstance(script, tuple):
            model.SetID(script[0])
            model.SetName(script[1])
            model.SetCreated(script[2])
            model.SetUpdated(script[3])
            model.SetDeleted(script[4])
            model.isExist = True
        return model
    @staticmethod
    def AllFromDB(log):
        models = []
        mysql.SetLog(log)
        script = mysql.Select('person_type').FetchAll()
        for row in script:
            model = PersonTypeModel(row[0])
            model.SetName(row[1])
            model.SetCreated(row[2])
            model.SetUpdated(row[3])
            model.SetDeleted(row[4])
            model.isExist = True
            models.append(model)
        return models
# ===== person group data model =====
class PersonGroupModel(BaseModel):
    def __init__(self, ID=None):
        super().__init__()
        self.table = 'person_group'
        if ID is not None:
            self.data['no'] = ID
        self.data['name'] = None
    # ===== id ========================================
    def SetID(self, ID):
        return self.SetValue('no', ID, int, False)
    def GetID(self):
        return self.data['no'] if 'no' in self.data else None
    # ===== name ========================================
    def SetName(self, name):
        return self.SetValue('name', name, str, False)
    def GetName(self):
        return self.data['name'] if 'name' in self.data else None
    def GetOldName(self):
        return self.change['name']
    def HasChangeName(self):
        return 'name' in self.change
    # ===== operate database ========================================
    def InsertToDB(self, log):
        keys = self.data.keys()
        values = [ self.data[x] for x in keys ]
        mysql.SetLog(log)
        script = mysql.Insert(self.table, keys, values)
        return script.Fetch()
    def UpdateToDB(self, log):
        script = None
        for k in self.data.keys():
            mysql.SetLog(log)
            script = mysql.Update(self.table, k, self.data[k]) if script is None else script.Add(k, self.data[k])
        script = script.Where('no', '=', self.data['no'])
        return script.FetchOne()
    def DeleteFromDB(self, log):
        mysql.SetLog(log)
        script = mysql.Delete(self.table).Where('no', '=', self.data['no'])
        return script.FetchOne()
    def ToDict(self):
        return {
            'ID': self.GetID(),
            'Name': self.GetName(), 
        }
    @staticmethod
    def FromDB(ID, log):
        model = PersonGroupModel(ID)
        mysql.SetLog(log)
        script = mysql.Select('person_group').Where('no', '=', ID).FetchOne()
        if isinstance(script, tuple):
            model.SetName(script[1])
            model.isExist = True
        return model
    @staticmethod
    def FromName(name, log):
        model = PersonGroupModel()
        mysql.SetLog(log)
        script = mysql.Select('person_group').Where('name', '=', name).FetchOne()
        if isinstance(script, tuple):
            model.SetID(script[0])
            model.SetName(script[1])
            model.SetCreated(script[2])
            model.SetUpdated(script[3])
            model.SetDeleted(script[4])
            model.isExist = True
        return model
    @staticmethod
    def AllFromDB(log):
        models = []
        mysql.SetLog(log)
        script = mysql.Select('person_group').FetchAll()
        if isinstance(script, tuple):
            for row in script:
                model = PersonGroupModel(row[0])
                model.SetName(row[1])
                model.SetCreated(row[2])
                model.SetUpdated(row[3])
                model.SetDeleted(row[4])
                model.isExist = True
                models.append(model)
        return models
# ===== person group relation data model =====
class PersonGroupRelationModel(BaseModel):
    def __init__(self, person_id=None,person_group_id=None):
        super().__init__()
        self.table = 'person_group_relation'
        self.data['person_id'] = person_id if isinstance(person_id, str) or person_id is None else str(person_id) 
        self.data['person_group_id'] = person_group_id if isinstance(person_group_id, str) or person_group_id is None else str(person_group_id) 
    # ===== device id ========================================
    def GetPersonID(self):
        return self.data['person_id'] if 'person_id' in self.data else None
    # ===== group id ========================================
    def GetPersonGroupID(self):
        return self.data['person_group_id'] if 'person_group_id' in self.data else None
    # ===== operate database ========================================
    def InsertToDB(self, log):
        keys = self.data.keys()
        values = [ self.data[x] for x in keys ]
        mysql.SetLog(log)
        script = mysql.Insert(self.table, keys, values)
        return script.Fetch()
    def DeleteFromDB(self, log):
        script = mysql.Delete(self.table).Where('person_id', '=', self.GetPersonID()).And('person_group_id', '=', self.GetPersonGroupID())
        mysql.SetLog(log)
        return script.FetchOne()
    def ToDict(self):
        return {
            'PersonID': self.GetPersonID(),
            'PersonGroupID': self.GetPersonGroupID()
        }
    # ===== other ========================================
    @staticmethod
    def FromDB(person_id,person_group_id, log):            
        model = PersonGroupRelationModel(person_id,person_group_id)
        mysql.SetLog(log)
        script = mysql.Select('person_group_relation').Where('person_id', '=', person_id).And('person_group_id', '=', person_group_id).FetchOne()
        if isinstance(script, tuple):
            model.SetCreated(script[2])
            model.SetUpdated(script[3])
            model.SetDeleted(script[4])
            model.isExist = True
        return model
    @staticmethod
    def AllPersonFromDB(person_group_id, log):
        models = []
        mysql.SetLog(log)
        script = mysql.Select('person_group_relation').Where('person_group_id', '=', person_group_id).FetchAll()
        if isinstance(script, tuple):
            for row in script:
                model = PersonGroupRelationModel(row[0],row[1])
                model.SetCreated(row[2])
                model.SetUpdated(row[3])
                model.SetDeleted(row[4])
                model.isExist = True
                models.append(model)
        return models
    @staticmethod
    def AllGroupFromDB(person_id, log):
        models = []
        mysql.SetLog(log)
        script = mysql.Select('person_group_relation').Where('person_id', '=', person_id).FetchAll()
        if isinstance(script, tuple):
            for row in script:
                model = PersonGroupRelationModel(row[0],row[1])
                model.SetCreated(row[2])
                model.SetUpdated(row[3])
                model.SetDeleted(row[4])
                model.isExist = True
                models.append(model)
        return models
    @staticmethod
    def AllFromDB(log):
        models = []
        mysql.SetLog(log)
        script = mysql.Select('person_group_relation').FetchAll()
        if isinstance(script, tuple):
            for row in script:
                model = PersonGroupRelationModel(row[0],row[1])
                model.SetCreated(row[2])
                model.SetUpdated(row[3])
                model.SetDeleted(row[4])
                model.isExist = True
                models.append(model)
        return models            
# ===== person group and device group relation data model =====
class PersonGroupAndDeviceGroupRelationModel(BaseModel):
    def __init__(self, person_group_id=None,device_group_id=None):
        super().__init__()
        self.table = 'person_group_and_device_group_relation'
        self.data['person_group_id'] = person_group_id if isinstance(person_group_id, str) or person_group_id is None else str(person_group_id) 
        self.data['device_group_id'] = device_group_id if isinstance(device_group_id, str) or device_group_id is None else str(device_group_id) 
    # ===== person group id ========================================
    def GetPersonGroupID(self):
        return self.data['person_group_id'] if 'person_group_id' in self.data else None
    # ===== device group id ========================================
    def GetDeviceGroupID(self):
        return self.data['device_group_id'] if 'device_group_id' in self.data else None
    # ===== operate database ========================================
    def InsertToDB(self, log):
        keys = self.data.keys()
        values = [ self.data[x] for x in keys ]
        mysql.SetLog(log)
        script = mysql.Insert(self.table, keys, values)
        return script.Fetch()
    def DeleteFromDB(self, log):
        script = mysql.Delete(self.table).Where('person_group_id', '=', self.GetPersonGroupID()).And('device_group_id', '=', self.GetDeviceGroupID())
        mysql.SetLog(log)
        return script.FetchOne()
    def ToDict(self):
        return {
            'PersonGroupID': self.GetPersonGroupID(),
            'DeviceGroupID': self.GetDeviceGroupID()
        }
    # ===== other ========================================
    @staticmethod
    def FromDB(person_group_id,device_group_id, log):            
        model = PersonGroupAndDeviceGroupRelationModel(person_group_id,device_group_id)
        mysql.SetLog(log)
        script = mysql.Select('person_group_and_device_group_relation').Where('person_group_id', '=', person_group_id).And('device_group_id', '=', device_group_id).FetchOne()
        if isinstance(script, tuple):
            model.SetCreated(script[2])
            model.SetUpdated(script[3])
            model.SetDeleted(script[4])
            model.isExist = True
        return model
    @staticmethod
    def AllFromDB(log):
        models = []
        mysql.SetLog(log)
        script = mysql.Select('person_group_and_device_group_relation').FetchAll()
        if isinstance(script, tuple):
            for row in script:
                model = PersonGroupAndDeviceGroupRelationModel(row[0],row[1])
                model.SetCreated(row[2])
                model.SetUpdated(row[3])
                model.SetDeleted(row[4])
                model.isExist = True
                models.append(model)
        return models    
# ===== device type data model =====
class DeviceTypeModel(BaseModel):
    def __init__(self, ID=None):
        super().__init__()
        self.table = 'device_type'
        if(ID != None):
            self.data['no'] = ID if isinstance(ID, str) else str(ID) 
        self.data['name'] = None
        self.data['vendor'] = None
        self.data['vendor_contact_person'] = None
        self.data['vendor_contact_way'] = None
    # ===== id ========================================
    def GetID(self):
        return self.data['no'] if 'no' in self.data else None
    # ===== name ========================================
    def SetName(self, name):
        return self.SetValue('name', name, str, False)
    def GetName(self):
        return self.data['name'] if 'name' in self.data else None
    def GetOldName(self):
        return self.change['name']
    def HasChangeName(self):
        return 'name' in self.change
    # ===== vendor ========================================
    def SetVendor(self, vendor):
        return self.SetValue('vendor', vendor, str, False)
    def GetVendor(self):
        return self.data['vendor'] if 'vendor' in self.data else None
    def GetOldVendor(self):
        return self.change['vendor']
    def HasChangeVendor(self):
        return 'vendor' in self.change
    # ===== vendor contact person ========================================
    def SetVendorContactPerson(self, vendor_contact_person):
        return self.SetValue('vendor_contact_person', vendor_contact_person, str, True)
    def GetVendorContactPerson(self):
        return self.data['vendor_contact_person'] if 'vendor_contact_person' in self.data else None
    def GetOldVendorContactPerson(self):
        return self.change['vendor_contact_person']
    def HasChangeVendorContactPerson(self):
        return 'vendor_contact_person' in self.change
    # ===== vendor contact way ========================================
    def SetVendorContactWay(self, vendor_contact_way):
        return self.SetValue('vendor_contact_way', vendor_contact_way, str, True)
    def GetVendorContactWay(self):
        return self.data['vendor_contact_way'] if 'vendor_contact_way' in self.data else None
    def GetOldVendorContactWay(self):
        return self.change['vendor_contact_way']
    def HasChangeVendorContactWay(self):
        return 'vendor_contact_way' in self.change
    # ===== operate database ========================================
    def InsertToDB(self, log):
        keys = self.data.keys()
        values = [ self.data[x] for x in keys ]
        mysql.SetLog(log)
        script = mysql.Insert(self.table, keys, values)
        return script.Fetch()
    def UpdateToDB(self, log):
        script = None
        for k in self.data.keys():
            mysql.SetLog(log)
            script = mysql.Update(self.table, k, self.data[k]) if script is None else script.Add(k, self.data[k])
        script = script.Where('no', '=', self.data['no'])
        return script.FetchOne()
    def DeleteFromDB(self, log):
        script = mysql.Delete(self.table).Where('no', '=', self.data['no'])
        mysql.SetLog(log)
        return script.FetchOne()
    def ToDict(self):
        return {
            'ID': self.GetID(),
            'Name': self.GetName(),
            'Vendor': self.GetVendor(),
            'VendorContactPerson': self.GetVendorContactPerson(),
            'VendorContactWay': self.GetVendorContactWay(),
        }
    # ===== other ========================================
    @staticmethod
    def FromDB(ID, log):            
        model = DeviceTypeModel(ID)
        mysql.SetLog(log)
        script = mysql.Select('device_type').Where('no', '=', ID).FetchOne()
        if isinstance(script, tuple):
            model.SetName(script[1])
            model.SetVendor(script[2])
            model.SetVendorContactPerson(script[3])
            model.SetVendorContactWay(script[4])
            model.SetCreated(script[5])
            model.SetUpdated(script[6])
            model.SetDeleted(script[7])
            model.isExist = True
        return model
    @staticmethod
    def FromDBByName(Name, log):            
        model = DeviceTypeModel()
        mysql.SetLog(log)
        script = mysql.Select('device_type').Where('name', '=', Name).FetchOne()
        if isinstance(script, tuple):
            model = DeviceTypeModel(script[0])
            model.SetName(script[1])
            model.SetVendor(script[2])
            model.SetVendorContactPerson(script[3])
            model.SetVendorContactWay(script[4])
            model.SetCreated(script[5])
            model.SetUpdated(script[6])
            model.SetDeleted(script[7])
            model.isExist = True
        return model
    @staticmethod
    def AllFromDB(log):
        models = []
        mysql.SetLog(log)
        script = mysql.Select('device_type').FetchAll()
        for row in script:
            model = DeviceTypeModel(row[0])
            model.SetName(row[1])
            model.SetVendor(row[2])
            model.SetVendorContactPerson(row[3])
            model.SetVendorContactWay(row[4])
            model.SetCreated(row[5])
            model.SetUpdated(row[6])
            model.SetDeleted(row[7])
            model.isExist = True
            models.append(model)
        return models
# ===== device group data model =====
class DeviceGroupModel(BaseModel):
    def __init__(self, ID=None):
        super().__init__()
        self.table = 'device_group'
        if(ID != None):
            self.data['no'] = ID if isinstance(ID, str) else str(ID) 
        self.data['name'] = None
    # ===== id ========================================
    def GetID(self):
        return self.data['no'] if 'no' in self.data else None
    # ===== name ========================================
    def SetName(self, name):
        return self.SetValue('name', name, str, False)
    def GetName(self):
        return self.data['name'] if 'name' in self.data else None
    def GetOldName(self):
        return self.change['name']
    def HasChangeName(self):
        return 'name' in self.change
    # ===== operate database ========================================
    def InsertToDB(self, log):
        keys = self.data.keys()
        values = [ self.data[x] for x in keys ]
        mysql.SetLog(log)
        script = mysql.Insert(self.table, keys, values)
        return script.Fetch()
    def UpdateToDB(self, log):
        script = None
        for k in self.data.keys():
            mysql.SetLog(log)
            script = mysql.Update(self.table, k, self.data[k]) if script is None else script.Add(k, self.data[k])
        script = script.Where('no', '=', self.data['no'])
        return script.FetchOne()
    def DeleteFromDB(self, log):
        script = mysql.Delete(self.table).Where('no', '=', self.data['no'])
        mysql.SetLog(log)
        return script.FetchOne()
    def ToDict(self):
        return {
            'ID': self.GetID(),
            'Name': self.GetName()
        }
    # ===== other ========================================
    @staticmethod
    def FromDB(ID, log):            
        model = DeviceGroupModel(ID)
        mysql.SetLog(log)
        script = mysql.Select('device_group').Where('no', '=', ID).FetchOne()
        if isinstance(script, tuple):
            model.SetName(script[1])
            model.SetCreated(script[2])
            model.SetUpdated(script[3])
            model.SetDeleted(script[4])
            model.isExist = True
        return model
    @staticmethod
    def FromDBByName(Name, log):            
        model = DeviceGroupModel()
        mysql.SetLog(log)
        script = mysql.Select('device_type').Where('name', '=', Name).FetchOne()
        if isinstance(script, tuple):
            model = DeviceGroupModel(script[0])
            model.SetName(script[1])
            model.SetCreated(script[2])
            model.SetUpdated(script[3])
            model.SetDeleted(script[4])
            model.isExist = True
        return model
    @staticmethod
    def AllFromDB(log):
        models = []
        mysql.SetLog(log)
        script = mysql.Select('device_group').FetchAll()
        if isinstance(script, tuple):
            for row in script:
                model = DeviceGroupModel(row[0])
                model.SetName(row[1])
                model.SetCreated(row[2])
                model.SetUpdated(row[3])
                model.SetDeleted(row[4])
                model.isExist = True
                models.append(model)
        return models    
# ===== device group relation data model =====
class DeviceGroupRelationModel(BaseModel):
    def __init__(self, device_id=None,device_group_id=None):
        super().__init__()
        self.table = 'device_group_relation'
        self.data['device_id'] = device_id if isinstance(device_id, str) or device_id is None else str(device_id) 
        self.data['device_group_id'] = device_group_id if isinstance(device_group_id, str) or device_group_id is None else str(device_group_id) 
    # ===== device id ========================================
    def GetDeviceID(self):
        return self.data['device_id'] if 'device_id' in self.data else None
    # ===== group id ========================================
    def GetDeviceGroupID(self):
        return self.data['device_group_id'] if 'device_group_id' in self.data else None
    # ===== name ========================================
    def SetName(self, name):
        return self.SetValue('name', name, str, False)
    def GetName(self):
        return self.data['name'] if 'name' in self.data else None
    def GetOldName(self):
        return self.change['name']
    def HasChangeName(self):
        return 'name' in self.change
    # ===== operate database ========================================
    def InsertToDB(self, log):
        keys = self.data.keys()
        values = [ self.data[x] for x in keys ]
        mysql.SetLog(log)
        script = mysql.Insert(self.table, keys, values)
        return script.Fetch()
    def UpdateToDB(self, log):
        script = None
        for k in self.data.keys():
            mysql.SetLog(log)
            script = mysql.Update(self.table, k, self.data[k]) if script is None else script.Add(k, self.data[k])
        script = script.Where('no', '=', self.data['no'])
        return script.FetchOne()
    def DeleteFromDB(self, log):
        script = mysql.Delete(self.table).Where('device_id', '=', self.GetDeviceID()).And('device_group_id', '=', self.GetDeviceGroupID())
        mysql.SetLog(log)
        return script.FetchOne()
    def ToDict(self):
        return {
            'DeviceID': self.GetDeviceID(),
            'DeviceGroupID': self.GetDeviceGroupID()
        }
    # ===== other ========================================
    @staticmethod
    def FromDB(device_id,device_group_id, log):            
        model = DeviceGroupRelationModel(device_id,device_group_id)
        mysql.SetLog(log)
        script = mysql.Select('device_group_relation').Where('device_id', '=', device_id).And('device_group_id', '=', device_group_id).FetchOne()
        if isinstance(script, tuple):
            model.SetCreated(script[2])
            model.SetUpdated(script[3])
            model.SetDeleted(script[4])
            model.isExist = True
        return model
    @staticmethod
    def FromDBByName(Name, log):            
        model = DeviceGroupModel()
        mysql.SetLog(log)
        script = mysql.Select('device_type').Where('name', '=', Name).FetchOne()
        if isinstance(script, tuple):
            model = DeviceGroupModel(script[0])
            model.SetName(script[1])
            model.SetCreated(script[2])
            model.SetUpdated(script[3])
            model.SetDeleted(script[4])
            model.isExist = True
        return model
    @staticmethod
    def AllFromDB(log):
        models = []
        mysql.SetLog(log)
        script = mysql.Select('device_group_relation').FetchAll()
        if isinstance(script, tuple):
            for row in script:
                model = DeviceGroupRelationModel(row[0],row[1])
                model.SetCreated(row[2])
                model.SetUpdated(row[3])
                model.SetDeleted(row[4])
                model.isExist = True
                models.append(model)
        return models        
# ===== device data model =====
class DeviceModel(BaseModel):
    def __init__(self, ID):
        super().__init__()
        self.table = 'device'
        self.data['id'] = ID if isinstance(ID, str) else str(ID)
        self.data['host'] = None
        self.data['port'] = None
        self.data['type'] = None
    # ===== id ========================================
    def GetID(self):
        return self.data['id'] if 'id' in self.data else None
    # ===== host ========================================
    def SetHost(self, host):
        return self.SetValue('host', host, str, False)
    def GetHost(self):
        return self.data['host'] if 'host' in self.data else None
    def GetOldHost(self):
        return self.change['host']
    def HasChangeHost(self):
        return 'host' in self.change
    # ===== port ========================================
    def SetPort(self, port):
        return self.SetValue('port', port, int, False)
    def GetPort(self):
        return self.data['port'] if 'port' in self.data else None
    def GetOldPort(self):
        return self.change['port']
    def HasChangePort(self):
        return 'port' in self.change
    # ===== type ========================================
    def SetType(self, device_type):
        return self.SetValue('type', device_type, str, True)
    def GetType(self):
        return self.data['type'] if 'type' in self.data else None
    def GetOldType(self):
        return self.change['type']
    def HasChangeType(self):
        return 'type' in self.change
    # ===== location ========================================
    def SetLocation(self, location):
        return self.SetValue('location', location, str, True)
    def GetLocation(self):
        return self.data['location'] if 'location' in self.data else ""
    def GetOldLocation(self):
        return self.change['location']
    def HasChangeLocatoin(self):
        return 'location' in self.change
    # ===== operate database ========================================
    def InsertToDB(self, log):
        keys = self.data.keys()
        values = [ self.data[x] for x in keys ]
        mysql.SetLog(log)
        script = mysql.Insert(self.table, keys, values)
#         print(script.__dict__)
        return script.Fetch()
    def UpdateToDB(self, log):
        script = None
        for k in self.data.keys():
            mysql.SetLog(log)
            script = mysql.Update(self.table, k, self.data[k]) if script is None else script.Add(k, self.data[k])
        script = script.Where('id', '=', self.data['id'])
        return script.FetchOne()
    def DeleteFromDB(self, log):
        script = mysql.Delete(self.table).Where('id', '=', self.data['id'])
        mysql.SetLog(log)
        return script.FetchOne()
    # ===== operate device ========================================
    def InsertToDevice(self, person):
        device_type = self.GetType()
        device_type = int(device_type) if isinstance(device_type, str) else device_type
        if device_type == 2:
             # 人臉辨識攝影機
            face = '{0}.jpg'.format(os.path.join('static', 'person', person.GetID()))
            return insert_face("http://{}:{}".format(self.GetHost(), self.GetPort()),person.GetID(),int(person.GetSex()),face)
        if device_type == 5:
            data = {
                'Name': "personListRequest",
                'Data': {
                    'Action': "addPerson",
                    'PersonType': int(person.GetType()),
                    'PersonInfo': {
                        'PersonCover': 1,
                        'PersonId': person.GetID(),
                        'PersonName': person.GetName(),
                        'Sex': int(person.GetSex()),
                        'LimitTime': 0,
                        'PersonPhoto': person.GetPhoto(),
                    }
                }
            }
            start = person.GetStart()
            end = person.GetEnd()
            if start is not None and end is not None:
                data['Data']['PersonInfo']['StartTime'] = start.strftime("%Y-%m-%d %H:%M:%S")
                data['Data']['PersonInfo']['EndTime'] = end.strftime("%Y-%m-%d %H:%M:%S")
                data['Data']['PersonInfo']['LimitTime'] = 1
            res = requests.post(self.GetResource(), data=json.dumps(data)).json()
            self.ResultCode = res['Data']['Result'] if 'Result' in res['Data'] else res['Code']
            return res['Code'] == 1
        if device_type == 4:
            face = '{0}.jpg'.format(os.path.join('static', 'person', person.GetID()))
            url = "http://{0}:{1}/api/sw_server_add_pic".format(self.GetHost(), self.GetPort())
            data = {
                    'method': 'sw_server_add_pic',
                    'serverId': str(round(datetime.timestamp(person.GetCreated()))),
                    'faceRcgName': person.GetID(),
                    'faceID': person.GetID(),
                    'gender': int(person.GetSex()),
                    'uuid' : self.GetID()
                }
            files = { "imageURLValue": open(face,"rb") }
#             headers = {}
#             start = person.GetStart()
#             end = person.GetEnd()
#             if start is not None and end is not None:
#                 data['Data']['PersonInfo']['StartTime'] = start.strftime("%Y-%m-%d %H:%M:%S")
#                 data['Data']['PersonInfo']['EndTime'] = end.strftime("%Y-%m-%d %H:%M:%S")
#                 data['Data']['PersonInfo']['LimitTime'] = 1
            res = requests.post(url,data=data,files=files)
            json_res = json.loads(res.text)
            if 'entity' in res.text and 'errcode' in json_res['entity'] and 'errorcode' in json_res['entity']['errcode']:
                self.ResultCode = json_res['entity']['errcode']['errorcode']
            else:
                self.ResultCode = json_res['status']
#             print(res.text)
            if self.ResultCode == 0:
                return True
            else:
                return False
#            return True
    def UpdateToDevice(self, person):
        device_type = self.GetType()
        device_type = int(device_type) if isinstance(device_type, str) else device_type
        if device_type == 5:
            start = person.GetStart()
            end = person.GetEnd()
            if person.HasChangeType():
                data = {
                    'Name': "personListRequest",
                    'Data': {
                        'Action': "addPerson",
                        'PersonType': person.GetType(),
                        'PersonInfo': {
                            'PersonCover': 1,
                            'PersonId': person.GetID(),
                            'PersonName': person.GetName(),
                            'Sex': int(person.GetSex()),
                            'LimitTime': 0,
                            'PersonPhoto': person.GetPhoto(),
                        }
                    }
                }
                res = requests.post(self.GetResource(), data=json.dumps(data)).json()
    #             print(res)
                self.ResultCode = res['Data']['Result'] if 'Result' in res['Data'] else res['Code']
                if res['Code'] == 1:
                    data = {
                        'Name': "personListRequest",
                        'Data': {
                            'Action': "deletePerson",
                            'PersonType': person.GetOldType(),
                            'PersonId': person.GetID(),
                        }
                    }
                else:
                    return False
            else:
                data = {
                    'Name': "personListRequest",
                    'Data': {
                        'Action': "editPerson",
                        'PersonType': person.GetType(),
                        'PersonInfo': {
                            'PersonCover': 1,
                            'PersonId': person.GetID(),
                            'PersonName': person.GetName(),
                            'Sex': person.GetSex(),
                            'LimitTime': 0,
                            'PersonPhoto': person.GetPhoto(),
                        }
                    }
                }
            if start is not None and end is not None:
                data['Data']['PersonInfo']['StartTime'] = start.strftime("%Y-%m-%d %H:%M:%S")
                data['Data']['PersonInfo']['EndTime'] = end.strftime("%Y-%m-%d %H:%M:%S")
                data['Data']['PersonInfo']['LimitTime'] = 1
            res = requests.post(self.GetResource(), data=json.dumps(data)).json()
            self.ResultCode = res['Data']['Result'] if 'Result' in res['Data'] else res['Code']
            return res['Code'] == 1
        if device_type == 4:
            #delete
            url = "http://{0}:{1}/api/sw_server_del_pic".format(self.GetHost(), self.GetPort())
            data = {
                'method': 'sw_server_del_pic',
                'serverId': str(round(datetime.timestamp(person.GetCreated()))),
                'uuid' : self.GetID()
            }
            files=[]
            res = requests.post(url,data=data,files=dict(foo='bar'))
            #insert
            face = '{0}.jpg'.format(os.path.join('static', 'person', person.GetID()))
            url = "http://{0}:{1}/api/sw_server_add_pic".format(self.GetHost(), self.GetPort())
            data = {
                    'method': 'sw_server_add_pic',
                    'serverId': str(round(datetime.timestamp(person.GetCreated()))),
                    'faceRcgName': person.GetID(),
                    'faceID': person.GetID(),
                    'gender': int(person.GetSex()),
                    'uuid' : self.GetID()
                }
            files = { "imageURLValue": open(face,"rb") }
            res = requests.post(url,data=data,files=files)
            #sw_server_update_pic
#             face = '{0}.jpg'.format(os.path.join('static', 'person', person.GetID()))
#             url = "http://{0}:{1}/api/sw_server_update_pic".format(self.GetHost(), self.GetPort())
#             data = {
#                 'method': 'sw_server_update_pic',
#                 'serverId': str(round(datetime.timestamp(person.GetCreated()))),
#                 'faceRcgName': person.GetName(),
#                 'faceID': person.GetID(),
#                 'gender': int(person.GetSex()),
#                 'uuid' : self.GetID()
#                }
#             files = { "imageURLValue": open(face,"rb") }
#             res = requests.post(url,data=data,files=files)
#             print(requests.post(url,data=data,files=files))
            print(res.text)
            json_res = json.loads(res.text)
            if 'entity' in res.text:
                self.ResultCode = json_res['entity']['errcode']['errorcode']
            else:
                self.ResultCode = json_res['status']
#             print(res.text)
            if self.ResultCode == 0:
                return True
            else:
                return False
#            return True
    def DeleteFromDevice(self, person):
        device_type = self.GetType()
        device_type = int(device_type) if isinstance(device_type, str) else device_type
        if device_type == 5:
            data = {
                'Name': "personListRequest",
                'Data': {
                    'Action': "deletePerson",
                    'PersonType': int(person.GetType()),
                    'PersonId': person.GetID(),
                }
            }
            res = requests.post(self.GetResource(), data=json.dumps(data)).json()
            self.ResultCode = res['Data']['Result'] if 'Result' in res['Data'] else res['Code']
            return res['Code'] == 1
        if device_type == 4:
            url = "http://{0}:{1}/api/sw_server_del_pic".format(self.GetHost(), self.GetPort())
            data = {
                'method': 'sw_server_del_pic',
                'serverId': str(round(datetime.timestamp(person.GetCreated()))),
                'uuid' : self.GetID()
            }
            files=[]
            res = requests.post(url,data=data,files=dict(foo='bar'))
            if not res.text == "":
                json_res = json.loads(res.text)
                if 'entity' in res.text and 'errcode' in json_res['entity'] and 'errorcode' in json_res['entity']['errcode']:
                    self.ResultCode = json_res['entity']['errcode']['errorcode']
                else:
                    self.ResultCode = json_res['status']
            else:
                self.ResultCode = res.status_code
#             print(res.text)
            if self.ResultCode == 0:
                return True
            else:
                return False
#            return True
        if device_type == 2:
            # 人臉辨識攝影機
            self.ResultCode = delete_person("http://{}:{}".format(self.GetHost(), self.GetPort()),person.GetID())
            return self.ResultCode
    def ToDict(self):
        return {
            'ID': self.GetID(),
            'Host':self.GetHost(),
            'Port':self.GetPort(),
            'Location': self.GetLocation(),
            'Type':self.GetType(),
            'Enabled': self.IsEnabled(),
        }
    # ===== other ========================================
    def GetResource(self):
        host = self.GetHost()
        port = self.GetPort()
        return "http://{0}:{1}/Request".format(host, port)
    @staticmethod
    def FromDB(ID, log):
        model = DeviceModel(ID)
        mysql.SetLog(log)
        script = mysql.Select('device').Where('id', '=', ID).FetchOne()
        if isinstance(script, tuple):
            model.SetHost(script[1])
            model.SetPort(script[2])
            model.SetType(script[3])
            model.SetLocation(script[4])
            model.SetCreated(script[5])
            model.SetUpdated(script[6])
            model.SetDeleted(script[7])
            model.isExist = True
        return model
    @staticmethod
    def AllFromDB(log):
        models = []
        mysql.SetLog(log)
        script = mysql.Select('device').FetchAll()
        if not isinstance(script, bool):
            for row in script:
                model = DeviceModel(row[0])
                model.SetHost(row[1])
                model.SetPort(row[2])
                model.SetType(row[3])
                model.SetLocation(row[4])
                model.SetCreated(row[5])
                model.SetUpdated(row[6])
                model.SetDeleted(row[7])
                model.isExist = True
                models.append(model)
        return models
# # ===== record data model =====
# class RecordModel(BaseModel):
#     def __init__(self, ID):
#         super().__init__()
#         self.table = 'record'
#         self.data['id'] = ID
#         self.data['start'] = None
#         self.data['end'] = None
#         self.data['image1'] = None
#         self.data['image2'] = None
#     def SetStart(self, start):
#         return self.SetValue('start', self.DatetimeToString(start), str, False)
#     def SetEnd(self, end):
#         return self.SetValue('end', self.DatetimeToString(end), str, False)
#     def SetStartImage(self, image):
#         return self.SetValue('image1', image, False)
#     def SetEndImage(self, image):
#         return self.SetValue('image2', image, False)
#     def InsertToDB(self):
#         keys = self.data.keys()
#         values = [ self.data[x] for x in keys ]
#         script = mysql.Insert(self.table, keys, values)
#         return script.Fetch()
#     def UpdateToDB(self):
#         script = None
#         for k in self.data.keys():
#             script = mysql.Update(self.table, k, self.data[k]) if script is None else script.Add(k, self.data[k])
#         script = script.Where('id', '=', self.data['id'])
#         return script.FetchOne()
#     def DeleteFromDB(self):
#         script = mysql.Delete(self.table).Where('id', '=', self.data['id'])
#         return script.FetchOne()
#     @staticmethod
#     def FromDB(ID):
#         model = RecordModel(ID)
#         script = mysql.Select('record').Where('id', '=', ID).FetchOne()
#         if isinstance(script, tuple):
#             model.SetHost(script[1])
#             model.SetPort(script[2])
#             model.SetCreated(script[3])
#             model.SetUpdated(script[4])
#             model.SetDeleted(script[5])
#             model.isExist = True
#         return model
#     @staticmethod
#     def AllFromDB():
#         models = []
#         script = mysql.Select('record').FetchAll()
#         for row in script:
#             model = RecordModel(row[0])
#             model.SetHost(row[1])
#             model.SetPort(row[2])
#             model.SetCreated(row[3])
#             model.SetUpdated(row[4])
#             model.SetDeleted(row[5])
#             model.isExist = True
#             models.append(model)
#         return models
# # ===== 使用者特徵資料庫模型 =====
# class UserFeatureModel(BaseModel):
#     def __init__(self, no=None):
#         super().__init__()
#         self.table = 'user_feature'
#         if no is not None:
#             self.data['no'] = no
#         self.data['id'] = None
#         self.data['features'] = None
#         self.data['description'] = None
#     def SetNo(self, no):
#         return self.SetValue('no', no, False)
#     def SetID(self, ID):
#         return self.SetValue('id', ID, False)
#     def SetFeatures(self, features):
#         return self.SetValue('features', features, False)
#     def SetDescription(self, description):
#         return self.SetValue('description', description, False)
#     def InsertToDB(self):
#         keys = self.data.keys()
#         values = [ self.data[x] for x in keys ]
#         script = mysql.Insert(self.table, keys, values)
#         return script.Fetch()
#     def UpdateToDB(self):
#         script = None
#         for k in self.data.keys():
#             script = mysql.Update(self.table, k, self.data[k]) if script is None else script.Add(k, self.data[k])
#         script = script.Where('no', '=', self.data['no'])
#         return script.FetchOne()
#     def DeleteFromDB(self):
#         script = mysql.Delete(self.table).Where('no', '=', self.data['no'])
#         return script.FetchOne()
#     @staticmethod
#     def FromDB(no):
#         model = UserFeatureModel(no)
#         script = mysql.Select('user_feature').Where('no', '=', no).FetchOne()
#         if isinstance(script, tuple):
#             model.SetID(script[1])
#             model.SetFeatures(script[2])
#             model.SetDescription(script[3])
#             model.SetCreated(script[4])
#             model.SetUpdated(script[5])
#             model.SetDeleted(script[6])
#             model.isExist = True
#         return model
#     @staticmethod
#     def FromDescription(description):
#         model = UserFeatureModel()
#         script = mysql.Select('user_feature').Where('description', '=', description).FetchOne()
#         if isinstance(script, tuple):
#             model.SetNo(script[0])
#             model.SetID(script[1])
#             model.SetFeatures(script[2])
#             model.SetDescription(script[3])
#             model.SetCreated(script[4])
#             model.SetUpdated(script[5])
#             model.SetDeleted(script[6])
#             model.isExist = True
#         return model
#     @staticmethod
#     def FromAll():
#         script = mysql.Select('user_feature').Where("id", "IS NOT", None).And("deleted", "IS", None).FetchAll()
#         models = []
#         if isinstance(script, tuple):
#             for row in script:
#                 model = UserFeatureModel(row[0])
#                 model.SetID(row[1])
#                 model.SetFeatures(row[2])
#                 model.SetDescription(row[3])
#                 model.SetCreated(row[4])
#                 model.SetUpdated(row[5])
#                 model.SetDeleted(row[6])
#                 model.isExist = True
#                 models.append(model)
#         return models
# ===== 伺服器資料庫模型 =====
class ServerModel(BaseModel):
    def __init__(self, ID):
        super().__init__()
        self.table = 'server'
        self.data['id'] = ID
        self.data['host'] = None
        self.data['port'] = None
    def SetHost(self, host):
        return self.SetValue('host', host, str, False)
    def SetPort(self, port):
        return self.SetValue('port', port, int, False)
    def InsertToDB(self):
        keys = self.data.keys()
        values = [ self.data[x] for x in keys ]
        script = mysql.Insert(self.table, keys, values)
        return script.Fetch()
    def UpdateToDB(self):
        script = None
        for k in self.data.keys():
            script = mysql.Update(self.table, k, self.data[k]) if script is None else script.Add(k, self.data[k])
        script = script.Where('id', '=', self.data['id'])
        return script.FetchOne()
    def DeleteFromDB(self):
        script = mysql.Delete(self.table).Where('id', '=', self.data['id'])
        return script.FetchOne()
    @staticmethod
    def FromDB(ID):
        model = ServerModel(ID)
        script = mysql.Select('server').Where('id', '=', ID).FetchOne()
        if isinstance(script, tuple):
            model.SetHost(script[1])
            model.SetPort(script[2])
            model.SetCreated(script[3])
            model.SetUpdated(script[4])
            model.SetDeleted(script[5])
            model.isExist = True
        return model