// EditDeviceDlg.cpp : implementation file
//

#include "StdAfx.h"

#include "sqlite3.h"

#include "USBFilterEditor.h"
#include "EditDeviceDlg.h"

// CEditDeviceDlg dialog

IMPLEMENT_DYNAMIC(CEditDeviceDlg, CDialog)

BEGIN_MESSAGE_MAP(CEditDeviceDlg, CDialog)
    ON_COMMAND_RANGE(IDC_CHECK_CLASS, IDC_CHECK_REVISION, &CEditDeviceDlg::OnCheckBox)
    ON_CBN_SELCHANGE(IDC_COMBO_VENDOR, &CEditDeviceDlg::OnCbnSelchangeComboVendor)
END_MESSAGE_MAP()

CEditDeviceDlg::CEditDeviceDlg(CWnd* pParent /*=NULL*/) :
    CDialog(CEditDeviceDlg::IDD, pParent),
    m_nClassId(-1),
    m_nVendorId(-1),
    m_nProductId(-1),
    m_nRevision(-1),
    m_nAction(-1)
{

}

CEditDeviceDlg::~CEditDeviceDlg()
{

}

int CEditDeviceDlg::GetComboBoxValue(int nCheckId, int nComboId)
{
    int nValue = -1;

    CButton *pCheck = (CButton *)GetDlgItem(nCheckId);
    ASSERT(pCheck != NULL);

    if (pCheck->GetCheck() == BST_CHECKED)
    {
        CComboBox *pCombo = (CComboBox *)GetDlgItem(nComboId);
        ASSERT(pCombo != NULL);

        int nIndex = pCombo->GetCurSel();
        
        if (nIndex != -1)
        {
            nValue = static_cast<int>(pCombo->GetItemData(nIndex));
        }
        else
        {
            CString sValue;
            pCombo->GetWindowText(sValue);

            nValue = _ttoi(sValue);

            if (nValue == 0)
            {
                nValue = _tcstol(sValue, NULL, 16);
            }
        }        
    }

    return nValue;
}

void CEditDeviceDlg::SetComboCurSel(int nComboId, int nValue)
{
    CComboBox *pCombo = (CComboBox *)GetDlgItem(nComboId);
    ASSERT(pCombo != NULL);

    for (int nIndex = 0; nIndex < pCombo->GetCount(); ++nIndex)
    {
        int nItemValue = static_cast<int>(pCombo->GetItemData(nIndex));
        if (nValue == nItemValue)
        {
            pCombo->SetCurSel(nIndex);
            break;
        }
    }
}

int CEditDeviceDlg::GetEditValue(int nCheckId, int nComboId)
{
    int nValue = -1;

    CButton *pCheck = (CButton *)GetDlgItem(nCheckId);
    ASSERT(pCheck != NULL);

    if (pCheck->GetCheck() == BST_CHECKED)
    {
        CString sRev;
        GetDlgItemText(nComboId, sRev);

        nValue = _ttoi(static_cast<LPCTSTR>(sRev));
    }

    return nValue;
}

int CEditDeviceDlg::_InsertClasses(void *opaque, int argc, char **argv, char **azColName)
{
    CEditDeviceDlg *pThis = (CEditDeviceDlg *)opaque;
    ASSERT(pThis != NULL);
    return pThis->InsertClasses(argc, argv);
}

int CEditDeviceDlg::_InsertVendors(void *opaque, int argc, char **argv, char **azColName)
{
    CEditDeviceDlg *pThis = (CEditDeviceDlg *)opaque;
    ASSERT(pThis != NULL);
    return pThis->InsertVendors(argc, argv);
}

int CEditDeviceDlg::_InsertProducts(void *opaque, int argc, char **argv, char **azColName)
{
    CEditDeviceDlg *pThis = (CEditDeviceDlg *)opaque;
    ASSERT(pThis != NULL);
    return pThis->InsertProducts(argc, argv);
}

void CEditDeviceDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);

    if (pDX->m_bSaveAndValidate == TRUE)
    {
        m_nClassId = GetComboBoxValue(IDC_CHECK_CLASS, IDC_COMBO_CLASS);
        m_nVendorId = GetComboBoxValue(IDC_CHECK_VENDOR, IDC_COMBO_VENDOR);
        m_nProductId = GetComboBoxValue(IDC_CHECK_PRODUCT, IDC_COMBO_PRODUCT);
        m_nRevision = GetEditValue(IDC_CHECK_REVISION, IDC_EDIT_REVISION);

        CButton *pAllow = (CButton *)GetDlgItem(IDC_RADIO_ACTION_1);
        ASSERT(pAllow != NULL);
        m_nAction = (pAllow->GetCheck() == BST_CHECKED);
    }
    else
    {
        if (m_nClassId != -1)
        {
            CButton *pCheck = (CButton *)GetDlgItem(IDC_CHECK_CLASS);
            ASSERT(pCheck != NULL);
            pCheck->SetCheck(BST_CHECKED);
            OnCheckBox(IDC_CHECK_CLASS);
            SetComboCurSel(IDC_COMBO_CLASS, m_nClassId);
        }

        if (m_nVendorId != -1)
        {
            CButton *pCheck = (CButton *)GetDlgItem(IDC_CHECK_VENDOR);
            ASSERT(pCheck != NULL);
            pCheck->SetCheck(BST_CHECKED);
            OnCheckBox(IDC_CHECK_VENDOR);
            SetComboCurSel(IDC_COMBO_VENDOR, m_nVendorId);
            OnCbnSelchangeComboVendor();
        }

        if (m_nProductId != -1)
        {
            CButton *pCheck = (CButton *)GetDlgItem(IDC_CHECK_PRODUCT);
            ASSERT(pCheck != NULL);
            pCheck->SetCheck(BST_CHECKED);
            OnCheckBox(IDC_CHECK_PRODUCT);

            // The function call to OnCbnSelchangeComboVendor fills the
            // products but select the first product. Fix selection.
            SetComboCurSel(IDC_COMBO_PRODUCT, m_nProductId);
        }

        if (m_nRevision != -1)
        {
            CButton *pCheck = (CButton *)GetDlgItem(IDC_CHECK_REVISION);
            ASSERT(pCheck != NULL);
            pCheck->SetCheck(BST_CHECKED);
            OnCheckBox(IDC_CHECK_REVISION);

            CString sRev;
            sRev.Format(_T("0x%04x"), m_nRevision);
            SetDlgItemText(IDC_EDIT_REVISION, sRev);
        }

        CButton *pAllow = (CButton *)GetDlgItem(m_nAction ? IDC_RADIO_ACTION_1 : IDC_RADIO_ACTION_2);
        ASSERT(pAllow != NULL);
        pAllow->SetCheck(BST_CHECKED);
    }
}

BOOL CEditDeviceDlg::OnInitDialog()
{
    sqlite3 *pDb = ((CUSBFilterEditorApp*)AfxGetApp())->GetEditorDb();

    sqlite3_exec(pDb, "SELECT * FROM Classes;", _InsertClasses, this, NULL);
    sqlite3_exec(pDb, "SELECT * FROM Vendors;", _InsertVendors, this, NULL);

    return CDialog::OnInitDialog();
}

void CEditDeviceDlg::OnOK()
{
    UpdateData(TRUE);

    CDialog::OnOK();
}

int CEditDeviceDlg::InsertClasses(int argc, char **argv)
{
    ASSERT(argc == 2);

    CComboBox *pClass = (CComboBox *)GetDlgItem(IDC_COMBO_CLASS);
    ASSERT(pClass != NULL);

    CString sClass;
    sClass.Format(_T("%S (0x%02x)"), argv[1], atoi(argv[0]));

    int nIndex = pClass->AddString(sClass);
    ASSERT(nIndex != -1);
    pClass->SetItemData(nIndex, atoi(argv[0]));

    return 0;
}

int CEditDeviceDlg::InsertVendors(int argc, char **argv)
{
    ASSERT(argc == 2);

    CComboBox *pVender = (CComboBox *)GetDlgItem(IDC_COMBO_VENDOR);
    ASSERT(pVender != NULL);

    CString sVendor;
    sVendor.Format(_T("%S (0x%04x)"), argv[1], atoi(argv[0]));

    int nIndex = pVender->AddString(sVendor);
    ASSERT(nIndex != -1);
    pVender->SetItemData(nIndex, atoi(argv[0]));

    return 0;
}

int CEditDeviceDlg::InsertProducts(int argc, char **argv)
{
    CComboBox *pProduct = (CComboBox *)GetDlgItem(IDC_COMBO_PRODUCT);
    ASSERT(pProduct != NULL);

    CString sProduct;
    sProduct.Format(_T("%S (0x%04x)"), argv[1], atoi(argv[0]));

    int nIndex = pProduct->AddString(sProduct);
    ASSERT(nIndex != -1);
    pProduct->SetItemData(nIndex, atoi(argv[0]));

    return 0;
}

// CEditDeviceDlg message handlers

afx_msg void CEditDeviceDlg::OnCheckBox(UINT nId)
{
    CWnd *pDlgItem = GetDlgItem(nId + (IDC_COMBO_CLASS - IDC_CHECK_CLASS));
    ASSERT(pDlgItem != NULL);

    pDlgItem->EnableWindow(!pDlgItem->IsWindowEnabled());
}

void CEditDeviceDlg::OnCbnSelchangeComboVendor()
{
    CComboBox *pVender = (CComboBox *)GetDlgItem(IDC_COMBO_VENDOR);
    ASSERT(pVender != NULL);

    int nIndex = pVender->GetCurSel();
    ASSERT(nIndex != -1);

    if (nIndex != -1)
    {
        CComboBox *pProduct = (CComboBox *)GetDlgItem(IDC_COMBO_PRODUCT);
        ASSERT(pProduct != NULL);
        pProduct->ResetContent();

        DWORD_PTR nVendor = pVender->GetItemData(nIndex);

        CStringA sSelectProducts;
        sSelectProducts.Format("SELECT Product, Name FROM Products WHERE (Vendor = %d);", nVendor);

        sqlite3 *pDb = ((CUSBFilterEditorApp*)AfxGetApp())->GetEditorDb();

        sqlite3_exec(pDb, sSelectProducts, _InsertProducts, this, NULL);

        pProduct->SetCurSel(0);
    }
}
