# -*- coding: utf-8 -*-
import os
import time
import datetime
import sys
from ooredis import *

from django.core.management.base import BaseCommand
from mysite.personnel.models import Employee
from mysite.personnel.models.model_emp import format_pin 
from mysite.iclock.models import Device,Area
from django.db import IntegrityError ,connections
from mysite.utils import get_option 
from mysite.iclock.models.model_dininghall import Dininghall
from mysite.utils import get_option

conn = connections['default']
def set_user(emp_dict,emp):
	"""
		将字典转换为人员对象
	"""
	if emp_dict.has_key("PIN"):
		emp.PIN = format_pin(emp_dict.get("PIN"))
		
	if emp_dict.has_key("AccGroup") and emp_dict.get("AccGroup"):
		m_val = emp_dict.get("AccGroup")
		if m_val!='None':
		  emp.AccGroup = m_val
		
	if emp_dict.has_key("EName"):
		emp.EName = u"%s"%emp_dict.get("EName")
						
	if emp_dict.has_key("Privilege") and emp_dict.get("Privilege"):
		m_val = emp_dict.get("Privilege")
		if m_val!='None':
			emp.Privilege =m_val
		
	if emp_dict.has_key("TimeZones"):
		m_val = emp_dict.get("TimeZones")
		if m_val!='None':
			emp.TimeZones = m_val

	if emp_dict.has_key("Password"):
		from base.crypt import encryption
		try:
			emp.Password = encryption(emp_dict.get("Password"))
		except:
			emp.Password = encryption("123456")
	return emp

def set_dev(dev_dict,dev,new=False):
	'''
		将字典转化为设备对象
	'''
	for key,value in dev_dict.items():
		if key=="area":
			if new:
				value = Area.objects.get(pk=value)
				dev.area = value
			continue
		if key=="dining":
			if new:
				value = Dininghall.objects.all()[0]
				dev.dining = value
			continue
		if key=="alias": #处理中文乱码问题
			if new:
				try:
				    value=value.decode("utf-8") 
				    dev.alias=value
				    continue
				except:
				    pass
		if key=="device_name": #处理中文乱码问题
			if new:
				try:
				    value=value.decode("utf-8") 
				    dev.device_name=value
				    continue
				except:
				    pass
		if value == "None":#redis数据类型转换
			setattr(dev, key, None )
			continue
		if value == "False":#redis数据类型转换
			setattr(dev, key, False )
			continue
		if value == "True":#redis数据类型转换
			setattr(dev, key, True )
			continue
		try:		
			if  key !="alias" or  new:
				setattr(dev, key, str(value) )
		except:
			import traceback
			traceback.print_exc()
			continue
	return dev
   
def set_card(emp,cardNO):
	from mysite.personnel.models.model_issuecard import IssueCard,CARD_VALID,CARD_OVERDUE
	from mysite.personnel.models.model_iccard import ICcard
	if get_option("POS") or cardNO == "0" or (not cardNO.strip()) :
		return 
	try:
		tmp_issuecare = IssueCard.objects.filter(UserID=emp,cardstatus__in = [CARD_OVERDUE,CARD_VALID])
		if tmp_issuecare:#编辑
			if  tmp_issuecare[0].cardno <> cardNO:
#				old_card = tmp_issuecare[0].cardno
#				tmp_issuecare[0].cardstatus = CARD_STOP  #停用旧卡号
				tmp_issuecare[0].card_from_dev = True
				tmp_issuecare[0].cardno = cardNO
				tmp_issuecare[0].save(force_update=True)
		else:
			issuecard = IssueCard()
			issuecard.card_from_dev = True
			issuecard.UserID = emp
			issuecard.cardno = cardNO
			issuecard.issuedate = datetime.datetime.now().strftime("%Y-%m-%d")
			try:
				issuecard.save()
			except IntegrityError:
				conn._rollback()
				conn.close()
	except:
			import traceback
			traceback.print_exc()
			
def save_area(eid,epin):
    '''
    将人员的redis区域信息保存到数据库
    '''
    from mysite.iclock.models import Area
    from base.sync_api import get_area
    from mysite.personnel.models.model_emp import device_pin
    from mysite.sql_utils import p_query,p_execute,get_sql
    pin = device_pin(epin)
    m_list = get_area(pin)
    delete_sql="""
      delete from userinfo_attarea where employee_id = %s
    """
    insert_sql =  get_sql("sql","user_area_insert","iclock",{},{},True)
    sqlList = []
    p_execute(delete_sql%eid)
    for a in m_list:
        p_execute(insert_sql%{'employee_id':eid,'area_id':a})

def update_user(emps):
	"""
		更新服务器人员信息,使之与redis 同步
	"""
#	a = time.time()
	if emps:
		pin_dict = dict([(format_pin(e.get("PIN")),e) for e in emps])
		emp_objs = Employee.all_objects.filter(PIN__in=pin_dict.keys()) 
		db_emps_dict = emp_objs and dict([(e.PIN,e) for e in emp_objs]) or {}
		param_pins = pin_dict.keys()   # redis 中存在的人员PIN
		db_pins = db_emps_dict.keys()  # 数据库中存在的人员
		insert_emps = set(param_pins) - set(db_pins)
		update_emps = set(db_pins)
		oo_cmd = SortedSet("server:update")
		if get_option("SECURITY_AND_ZKECO") and len(insert_emps)>0:
			from mysite.inbiobutt.adms_butt import butt_dev_insert_emps 
			success_list = butt_dev_insert_emps(pin_dict,insert_emps)
		for e in insert_emps:
			if pin_dict.has_key(e):
				emp_dict = pin_dict.get(e)
				emp = Employee()
				try:
					emp = set_user(emp_dict,emp)
				except UnicodeError, e:
					import traceback
					print traceback.print_exc()
					oo_cmd.remove(emp_dict['mb'])
					continue
				if get_option("SECURITY_AND_ZKECO") and success_list:
					emp_id =success_list.get(e)
					emp.id = emp_id
				emp.DeptID_id = 1
				emp.from_dev = True
				oo_cmd.remove(emp_dict['mb'])	#些处删除"server:update"内容 
				try:
					super(Employee,emp).save()
				except IntegrityError:
#					conn._rollback()
					conn.close()
					db_emps_dict[e]=Employee.all_objects.filter(PIN__exact=format_pin(emp_dict.get("PIN")))[0] 
					update_emps.add(e)
					continue
				except Exception, e:
					import traceback;traceback.print_exc()
				
				#保存卡   
				if emp_dict.has_key("Card"):
					if emp_dict.get("Card"):
						set_card(emp,emp_dict.get("Card"))	
				 
				'''保存区域'''
				save_area(emp.id,emp.PIN)
				
		if get_option("SECURITY_AND_ZKECO") and len(update_emps)>0:
			from mysite.inbiobutt.adms_butt import butt_dev_update_emps 
			butt_dev_update_emps(pin_dict,db_emps_dict,update_emps)
		from django.db.models import Model	
		from django.core.cache import cache
		from base.cached_model import cache_key
		for e in update_emps:
			if db_emps_dict.has_key(e) and pin_dict.has_key(e):
				emp_dict = pin_dict.get(e)
				emp = db_emps_dict.get(e)
				try:
					emp = set_user(emp_dict,emp)
				except UnicodeError, e:
					import traceback
					print traceback.print_exc()
					oo_cmd.remove(emp_dict['mb'])
					continue
				emp.from_dev = True
				Model.save(emp)
				#清除缓存key，让页面显示保存一致
				key = cache_key(emp,emp.pk)
				cache.delete(key)
#				super(Employee,emp).save()	
				#保存卡
				oo_cmd.remove(emp_dict['mb'])	#些处删除"server:update"内容 
				if emp_dict.has_key("Card"):
					if emp_dict.get("Card"):
						set_card(emp,emp_dict.get("Card"))	
				'''更新'''
				save_area(emp.id,emp.PIN)
#	b = time.time()
#	print "time---------------------------------------",b-a
def update_device(devs):
	"""
		更新服务器数据库 设备信息,使之与redis 同步
	"""
	if devs:
		SN_dict = dict([(d.get("sn"),d) for d in devs])
		
		dev_objs = Device.objects.filter(sn__in=SN_dict.keys()) 
		len(dev_objs)
		db_devs_dict = dev_objs and dict([(d.sn,d) for d in dev_objs]) or {}
		
		param_SN = SN_dict.keys()   # redis 中存在的设备SN
		db_SN = db_devs_dict.keys()  # 数据库中存在的设备SN
		
		insert_devs = set(param_SN) - set(db_SN)
		update_devs = set(db_SN)
		
		oo_cmd = SortedSet("server:update")
		for d in insert_devs:
			if SN_dict.has_key(d):
				dev_dict = SN_dict.get(d)
				dev = Device()
				dev = set_dev(dev_dict,dev,new=True)
				dev.from_dev = True
				try:
					super(Device,dev).save(log_msg=False)
					oo_cmd.remove(dev_dict['mb'])	#些处删除"server:update"内容 
					
					if get_option("POS_IC") and dev.device_type == '5':#消费设备
						dev.set_all_pos_data()
				except IntegrityError:
#					conn._rollback()
					conn.close()	 
					update_devs.add(d)
					continue
				except Exception, e:
					import traceback;traceback.print_exc()
				
		for d in update_devs:
			if db_devs_dict.has_key(d) and SN_dict.has_key(d):
				dev_dict = SN_dict.get(d)
				dev = db_devs_dict.get(d)
				dev = set_dev(dev_dict,dev)
				dev.from_dev = True
				super(Device,dev).save(log_msg=False)
				oo_cmd.remove(dev_dict['mb'])	#些处删除"server:update"内容	

def clean_cache():
	from base.sync_api import get_device_status, clean_cache_data
	dev_objs = Device.objects.all()
	for obj in dev_objs:
		if not get_device_status(obj.sn):
			clean_cache_data(obj.sn)


def save_finnger(pin, ver, fingger, Valid, data):
	"""
	Save or update employee finger template information to database
    Used by writedata server
	:param pin: Employee badge number
	:param ver: Finger Version
	:param fingger: Finger ID
	:param Valid:
	:param data: Finger template
	:return:
	"""
	from mysite.sql_utils import p_execute, p_query_one
	from comm.att.struct.rmodel_base import TouchSync
	pin = format_pin(pin)
	template = data
	dict_val={
		"pin": pin,
		"FingerID": fingger,
		"Fpversion": ver,
		"template": template,
		"Valid": Valid
	}
	query_sql = """
		select Template, Valid from finger_template
        where pin = '%(pin)s' and FingerID='%(FingerID)s' and Fpversion = '%(Fpversion)s'
	""" % dict_val
	insert_sql = """
        insert into finger_template (status,bio_type,pin,Template,FingerID,Fpversion,Valid)
        values(0,0,'%(pin)s','%(template)s','%(FingerID)s','%(Fpversion)s',%(Valid)s)
	""" % dict_val
	update_sql = """
        update finger_template set Template = '%(template)s', Valid = %(Valid)s
        where pin = '%(pin)s' and FingerID='%(FingerID)s' and Fpversion = '%(Fpversion)s'
	""" % dict_val
	check_again = True
	res = p_query_one(query_sql)
	if res:
		if res[0] != template or res[1] != int(Valid):
			res = p_execute(update_sql)
			if res == 1: #更新成功
				check_again = False
		else:#数据重复不需要更新
			check_again = False
	else:
		res = p_execute(insert_sql)
		if res == 1: #插入成功
			check_again = False
	if check_again:
		key = 'finger%s|%s|%s' % (pin, ver, fingger)
		oo_server = SortedSet("server:update")
		TouchSync(oo_server, key)
	return res


def save_face(pin, ver, field, data):
	"""
	Save or update employee face template information to database
	Used by writedata server
	:param pin:
	:param ver:
	:param field:
	:param data:
	:return:
	"""
	from mysite.sql_utils import p_execute, p_query_one
	from comm.att.struct.rmodel_base import TouchSync
	pin = format_pin(pin)
	template = data
	dict_val={
		"pin": pin,
		"faceid": field,
		"face_ver": ver,
		"template": template
	}
	query_sql = """
        select facetemp from face_template
        where pin = '%(pin)s' and faceid='%(faceid)s' and face_ver = '%(face_ver)s'
	""" % dict_val
	insert_sql = """
        insert into face_template (status,valid,pin,facetemp,faceid,face_ver)
        values(0,1,'%(pin)s','%(template)s','%(faceid)s','%(face_ver)s')
	""" % dict_val
	update_sql = """
        update face_template set facetemp = '%(template)s'
        where pin = '%(pin)s' and faceid='%(faceid)s' and face_ver = '%(face_ver)s'
	""" % dict_val
	check_again = True
	res = p_query_one(query_sql)
	if res:
		if str(res[0]) != str(template): #已存在数据且需要更新
			res = p_execute(update_sql)
			if res == 1: #更新成功
				check_again = False
		else: #已存在数据但不需要更新
			check_again = False
	else:
		res = p_execute(insert_sql)
		if res == 1: #插入成功
			check_again = False
	if check_again:
		key = 'face%s|%s|%s' % (pin, ver, field)
		oo_server = SortedSet("server:update")
		TouchSync(oo_server, key)
	return res

from mysite.dbutils_pool import getConn

def p_execute(sql):
    conn = None
    cur = None
    res = None 
    try:
        conn =  getConn()
        cur = conn.cursor()            
        cur.execute(sql)
        res = cur._cursor.rowcount
        conn.commit()
    except Exception ,e:
        if conn:
            conn.rollback()
        traceback.print_exc()
    finally:
        if res == -1: # 可能是数据库断开连接
            ret,msg =test_conn()
            if not ret:
                reConn()
                res = -2
        if cur:
            cur.close()
        if conn:
            conn.close()
        return res

def save_finnger_bak(pin, ver, fingger, Valid, data):
    '''
    保存指纹到数据库
    '''
    from comm.att.struct.rmodel_base import TouchSync

    pin = format_pin(pin)
    template = data
    dict_val={
                  "pin":pin,
                  "FingerID":fingger,
                  "Fpversion":ver,
                  "template":template,
                  "Valid":Valid
              }
    sql_update ="""
         update 
                finger_template 
             set Template = '%(template)s',
                 Valid = %(Valid)s
        where 
             pin = '%(pin)s' and FingerID='%(FingerID)s' and Fpversion = '%(Fpversion)s' 
    """ %dict_val
    
    sql_insert = """
        insert into 
            finger_template (status,bio_type,pin,Template,FingerID,Fpversion,Valid) 
            values(0,0,'%(pin)s','%(template)s','%(FingerID)s','%(Fpversion)s',%(Valid)s)
    """ % dict_val
    res = p_execute(sql_update)
    if res == 0 :
        res = p_execute(sql_insert)
    return res

def save_face_bak(pin, ver, field, data):
    u'''
        保存面部到数据库
    '''
    from comm.att.struct.rmodel_base import TouchSync
    pin = format_pin(pin)
    faceid = field
    template = data
    dict_val={
                  "pin":pin,
                  "faceid":field,
                  "face_ver":ver,
                  "template":template
              }
    sql_update ="""
         update 
                face_template 
             set facetemp = '%(template)s'
        where 
             pin = '%(pin)s' and faceid='%(faceid)s' and face_ver = '%(face_ver)s' 
    """ %dict_val
    
    sql_insert = """
        insert into 
            face_template (status,valid,pin,facetemp,faceid,face_ver) 
            values(0,1,'%(pin)s','%(template)s','%(faceid)s','%(face_ver)s')
    """ % dict_val
    res = p_execute(sql_update)
    if res == 0 :
        res = p_execute(sql_insert)

    return res

#[{'key':['1|10|1'],'mb':1001}]
def update_finger(fingers):
	from comm.att.struct.sync_store import load_finnger
	from comm.att.struct.rmodel_fingerprint import FingerPrint
	if fingers:
		oo_cmd = SortedSet("server:update")
		for finger in fingers:
			key = finger.get('key')
			pin,ver,fingger = key.split('|')
			r_finger = FingerPrint(pin=pin, Fpversion=ver)
			fd = [key for key in r_finger.getoo().keys() if key.startswith('fp')]
			# fd = load_finnger('%s|%s'%(pin,ver))
			if fd:
				key = "fp"+fingger
				if key in fd:
					data = r_finger.getoo()[key]
					save_finnger(pin, ver, fingger, 1, data)
			oo_cmd.remove(finger.get('mb'))

#[{'key':['1|7|1'],'mb':1001}]
def update_face(faces):
	from comm.att.struct.sync_store import load_face
	from comm.att.struct.rmodel_face import Face
	if faces:
		oo_cmd = SortedSet("server:update")
		for face in faces:
			key = face.get('key')
			pin,ver,field = key.split('|')
			# fd = load_face('%s|%s'%(pin,ver))
			r_face = Face(pin=pin, face_ver=ver)
			fd = [key for key in r_face.getoo().keys() if key.startswith('face')]
			if fd:
				key = "face"+field
				if key in fd:
					data = r_face.getoo()[key]
					save_face(pin, ver, field, data)
			oo_cmd.remove(face.get('mb'))

def index_fp_db():
	from comm.att.struct.sync_store import load_finnger, index_finnger
	from comm.att.struct import sync_action
	m_list = index_finnger()
	for e in m_list:
		print e
		fd = load_finnger('%s|%s'%(e[0], e[1]))
		if fd:
			for f in fd:
				data = fd.get(f)
				save_finnger(e[0], e[1], f.replace('fp',''), 1, data)

def index_face_db():
	from comm.att.struct.sync_store import load_face, index_face
	from comm.att.struct import sync_action
	m_list = index_face()
	for e in m_list:
		print e
		fd = load_face('%s|%s'%(e[0], e[1]))
		if fd:
			for f in fd:
				data = fd.get(f)
				save_face(e[0], e[1], f.replace('face',''), data)

	