// TagAccess.cpp : 实现文件
//

#include "stdafx.h"
#include "R2kDemo.h"
#include "TagAccess.h"
//#include "R2kDemo.h"


// CTagAccess 对话框

IMPLEMENT_DYNAMIC(CTagAccess, CPropertyPage)

CTagAccess::CTagAccess()
	: CPropertyPage(CTagAccess::IDD)
	, m_dataLength(0)
	, m_pwd(_T(""))
	, m_data(_T(""))
	, m_lockpwd(_T(""))
	, m_killpwd(_T(""))
	, m_killAccPwd(_T(""))
{

}

CTagAccess::~CTagAccess()
{
}

void CTagAccess::DoDataExchange(CDataExchange* pDX)
{
	CPropertyPage::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_COMBO_BANK, m_bank);
	DDX_Control(pDX, IDC_COMBO_BEGIN, m_begin);
	DDX_Control(pDX, IDC_COMBO_LENGTH, m_length);
	DDX_Text(pDX, IDC_EDIT_ACCPWD, m_pwd);
	DDX_Control(pDX, IDC_COMBO_LOCKTYPE, m_locktype);
	DDX_Control(pDX, IDC_COMBO_LOCKBANK, m_oprarea);
	DDX_Text(pDX, IDC_EDIT_DATA, m_data);
	DDX_Control(pDX, IDC_EDIT_DATA, m_ctlData);
	DDX_Text(pDX, IDC_EDIT_LOCKPWD, m_lockpwd);
	DDX_Text(pDX, IDC_EDIT_KILLPWD, m_killpwd);
	DDX_Text(pDX, IDC_EDIT_KILLACCPWD, m_killAccPwd);
}


BEGIN_MESSAGE_MAP(CTagAccess, CPropertyPage)
	ON_CBN_SELCHANGE(IDC_COMBO_BANK, &CTagAccess::OnCbnSelchangeComboBank)
	ON_CBN_SELCHANGE(IDC_COMBO_BEGIN, &CTagAccess::OnCbnSelchangeComboBegin)
	ON_BN_CLICKED(IDC_BTN_READ, &CTagAccess::OnBnClickedBtnRead)
	ON_BN_CLICKED(IDC_BTN_WRITE, &CTagAccess::OnBnClickedBtnWrite)
	ON_BN_CLICKED(IDC_BTN_LOCK, &CTagAccess::OnBnClickedBtnLock)
	ON_BN_CLICKED(IDC_BTN_KILL, &CTagAccess::OnBnClickedBtnKill)
	ON_EN_CHANGE(IDC_EDIT_DATA, &CTagAccess::OnEnChangeEditData)
	ON_BN_CLICKED(IDC_BTN_CLRDATA, &CTagAccess::OnBnClickedBtnClrdata)
END_MESSAGE_MAP()


// CTagAccess 消息处理程序

BOOL  CTagAccess::OnInitDialog(void)
{
	CPropertyPage::OnInitDialog();
	// Access area
	m_bank.AddString("Reserve");
	m_bank.AddString("EPC");
	m_bank.AddString("TID");
	m_bank.AddString("User");

	// Lock type
	m_locktype.AddString("Unlock");
	m_locktype.AddString("Permanence writable");
	m_locktype.AddString("Security Lock");
	m_locktype.AddString("Permanence unwritable");

	// operating area
	m_oprarea.AddString("Kill");
	m_oprarea.AddString("Access");
	m_oprarea.AddString("EPC");
	m_oprarea.AddString("TID");
	m_oprarea.AddString("User");
	m_pwd = CString("00000000"); // 默认访问密码
	UpdateData(FALSE);
	return false;
}

void CTagAccess::OnCbnSelchangeComboBank() // 根据选择的bank不同，添加不同地址范围
{
	CString str;
	m_bank.GetWindowText(str);
	int start = 0 ,  end = 0;

	if (str == CString("EPC"))
	{
		start = 2; 
		end = 7;
		m_dataLength = 8;  // 有效数据长度(word)
	}
	else if (str == CString("Reserve"))
	{
		start = 0; 
		end = 3;
		m_dataLength = 4;
	}
	else if ( str == CString ("TID"))
	{
		start = 0; 
		end = 5;
		m_dataLength = 6;
	}
	else if ( str == CString ("User"))
	{
		start = 0; 
		end = 31;
		m_dataLength = 32;
	}

	m_begin.ResetContent(); // 删除以前的选项

	for (int i = start  ; i <= end; ++i)
	{
		str.Format("%d",  i );
		m_begin.AddString(str);
	}
}

void CTagAccess::OnCbnSelchangeComboBegin()	// 设置长度范围
{
	m_length.ResetContent();
	// 计算数据范围
	CString  str;
	m_begin.GetWindowText(str); // 获取起始点文本
	int begin = 1;
	int end = m_dataLength -  atoi(str.GetBuffer()); // 最大数据长度

	CString temp;
	for (int index = begin; index <=  end; ++index)
	{
		temp.Format("%d", index);
		m_length.AddString(temp);
	}
}

BOOL CTagAccess::OnSetActive()
{
	BOOL bConnected = ((CR2kDemoApp*)AfxGetApp())->m_connected;
	GetDlgItem(IDC_BTN_READ)->EnableWindow(bConnected);
	GetDlgItem(IDC_BTN_WRITE)->EnableWindow(bConnected);
	GetDlgItem(IDC_BTN_LOCK)->EnableWindow(bConnected);
	GetDlgItem(IDC_BTN_KILL)->EnableWindow(bConnected);

	return CPropertyPage::OnSetActive();
}

void CTagAccess::OnBnClickedBtnRead()
{
	UpdateData();
	unsigned char bank = m_bank.GetCurSel();
	if (bank > 4)	// 没有选择时，bank 为255(-1)
	{
		MessageBox(_T("请选择操作区域！"), _T("错误"), 0);
		return;
	}
	int index = m_begin.GetCurSel();
	if (-1 == index)	// 没有选择有效项目
	{
		MessageBox(_T("请选择起始地址！"), _T("错误"), 0);
		return;
	}
	// bank为EPC(1)时，起始地址为2
	unsigned char begin =  (1 == bank) ?  (2 + index) : index ;
	index = m_length.GetCurSel();
	if (-1 == index)	// 没有选择有效项目
	{
		MessageBox(_T("请选择长度！"), _T("错误"), 0);
		return;
	}
	unsigned char length = m_length.GetCurSel() + 1; // 选择项索引从0开始

	char pwd[8] = {0};
	m_pwd.Remove(' ');
	for (int i = 0; i < 4; ++i)
		sscanf(m_pwd.GetBuffer() + 2 * i, "%2hhX", &pwd[i]);

	unsigned char buf[128] = {0};// 接收缓冲区	
	if (R_OK == ReadTagData(bank, begin, length, &buf[0], &pwd[0]))
	{
		CString temp;
		m_data = CString("");
		for(int i = 0; i < length *2; ++i)
		{
			temp.Format("%02X ", buf[i]);
			m_data += temp;
		}
			UpdateData(FALSE);
			GetDlgItem(IDC_STA_RESULT)->SetWindowText("读取成功.");
	}
	else
	{
		GetDlgItem(IDC_STA_RESULT)->SetWindowText("读取失败.");
	}	
}

void CTagAccess::OnBnClickedBtnWrite()
{
	UpdateData();
	unsigned char bank = m_bank.GetCurSel();
	if (bank > 4 || 2 == bank)	// 没有选择时，bank 为255(-1), TID(2)不可写
	{
		MessageBox(_T("请选择正确的操作区域！"), _T("错误"), 0);
		return;
	}
	if (m_data.GetLength() == 0)
	{
		MessageBox(_T("没有数据."), _T("错误"), 0);
		return;
	}
	int index = m_begin.GetCurSel();
	if (-1 == index)	// 没有选择有效项目
	{
		MessageBox(_T("请选择起始地址！"), _T("错误"), 0);
		return;
	}
	// bank为EPC(1)时，起始地址为2
	unsigned char begin =  (1 == bank) ?  (2 + index) : index ;
	//index = m_length.GetCurSel();
	//if (-1 == index)	// 没有选择有效项目
	//{
	//	MessageBox(_T("请选择长度！"), _T("错误"), 0);
	//	return;
	//}
	//unsigned char length = m_length.GetCurSel() + 1;
	// 转换密码
	char pwd[8] = {0};
	m_pwd.Remove(' ');
	for (int i = 0; i < 4; ++i)
		sscanf(m_pwd.GetBuffer() + 2 * i, "%2hhX ", &pwd[i]);
	m_data.Remove(' '); // 去除加入的空格
	//	转换写入数据
	if (CharIsValid(m_data))
	{
		int MaxLength = 0;
		if (bank == 1) // EPC区域
		{
			MaxLength = 8 - begin;		
		}
		else if ( bank == 0) // 保留区
		{
			MaxLength = 4 - begin;
		}
		else if (bank = 3)  // 用户区
		{
			MaxLength = 32 - begin;
		}
		BYTE length = m_data.GetLength() / 4; // 换算为字数
		if (length > MaxLength)
		{
			MessageBox(_T("数据长度超过最大值."),  _T("信息"), 0);
			return;
		}

		unsigned char buf[128] = {0};
		for (int index = 0; index <= length * 2; ++index)
		{
			sscanf(m_data.GetBuffer() + 2 * index, "%2hhX", &buf[index]);
		}
		if (R_OK == WriteTagData(bank, begin, length, &buf[0], &pwd[0]))
		{
			GetDlgItem(IDC_STA_RESULT)->SetWindowText("写入成功.");
		}
		else
		{
			GetDlgItem(IDC_STA_RESULT)->SetWindowText("写入失败.");
		}
	}
}

void CTagAccess::OnBnClickedBtnLock()
{
	UpdateData();
	int locktype = m_locktype.GetCurSel();
	if ( -1 == locktype)
	{
		MessageBox(_T("请选择锁卡类型！"), _T("错误"), 0);
		return;
	}
	int oprarea = m_oprarea.GetCurSel();
	if ( -1 == oprarea)
	{
		MessageBox(_T("请选择锁卡区域！"), _T("错误"), 0);
		return;
	}
	m_lockpwd.Remove(' ');
	if (m_lockpwd.GetLength() < 8)
	{
		MessageBox(_T("密码位数不足！"), _T("错误"), 0);
		return;
	}
	char pwd[8] = {0};
	for (int i = 0; i < 4; ++i)
		sscanf(m_lockpwd.GetBuffer() + 2 * i, "%2hhX ", &pwd[i]);
	if ( R_OK == LockTag(locktype, oprarea, &pwd[0]))
	{
		GetDlgItem(IDC_STA_RESULT)->SetWindowText("操作成功.");
	}
	else
	{
		GetDlgItem(IDC_STA_RESULT)->SetWindowText("操作失败.");
	}	
}

void CTagAccess::OnBnClickedBtnKill()
{
	UpdateData();
	m_killAccPwd.Remove(' ');
	if (m_killAccPwd.GetLength() < 8)
	{
		MessageBox(_T("访问密码位数不足！"), _T("错误"), 0);
		return;
	}
	m_killAccPwd.Remove(' ');
	if (m_killpwd.GetLength() < 8)
	{
		MessageBox(_T("销毁密码位数不足！"), _T("错误"), 0);
		return;
	}
	char accpwd[8] = {0};
	for (int i = 0; i < 4; ++i)
		sscanf(m_killAccPwd.GetBuffer() + 2 * i, "%2hhX ", &accpwd[i]);
	char killpwd[8] = {0};
	for (int i = 0; i < 4; ++i)
		sscanf(m_killpwd.GetBuffer() + 2 * i, "%2hhX ", &killpwd[i]);
	if (R_OK == KillTag((unsigned char*)&killpwd[0], (unsigned char*)&accpwd[0]))
	{
		GetDlgItem(IDC_STA_RESULT)->SetWindowText("销毁成功.");
	}
	else
	{
		GetDlgItem(IDC_STA_RESULT)->SetWindowText("销毁失败.");
	}		
}

void CTagAccess::OnEnChangeEditData()
{  // 自动添加空格，并把光标设置到最后
	//UpdateData();
	//int length = m_data.GetLength();
	////CString temp;
	////temp.Format("length = %d", length);
	//if ( length % 3 == 2)
	//{
	//	//MessageBox(temp, temp, 0);
	//	m_data += CString(" ");
	//	UpdateData(FALSE);
	//	int nStart, nEnd;

	//	m_ctlData.GetSel(nStart, nEnd);// 把光标位置设置到最后
	//	if(nStart == nEnd)
	//	{
	//		m_ctlData.SetSel(nStart+length +1, nEnd+length +1); 
	//	}
	//}
}

void CTagAccess::OnBnClickedBtnClrdata()
{
	m_data = CString("");
	UpdateData(FALSE);
}

BOOL CTagAccess::CharIsValid(CString& str)
{
	int length = str.GetLength();
	if (0 == length)
	{
		MessageBox(_T("没有数据"), _T("错误"), 0);
		return FALSE;
	}
	for (int i = 0; i < length;  ++i) // 检查字符是否为无效字符
	{
		char ch = str.GetAt(i);
		if ( (ch <  '0')   ||
			(ch > '9' && ch < 'A') ||
			(ch > 'F'  && ch < 'a') ||
			(ch  > 'f'))
		{
			MessageBox(_T("含有无效字符"), _T("错误"), 0);
			return FALSE;
		}
	}
	if (length % 4 != 0)
	{
		MessageBox(_T("数据位数必须是4的整倍数"), _T("错误"), 0);
		return FALSE;
	}
	return TRUE;
}
