// SettingOptionPage.cpp : 구현 파일입니다.
//

#include "stdafx.h"
#include "PatchMaker.h"
#include "SettingOptionPage.h"

#include "UtilityFunc.h"
#include "PMSettingConstant.h"
#include ".\settingoptionpage.h"

// CSettingOptionPage 대화 상자입니다.

IMPLEMENT_DYNAMIC(CSettingOptionPage, CPropertyPage)
CSettingOptionPage::CSettingOptionPage(CPMSetting& pmSetting, CPropertySheet& ownerSheet)
    : CPropertyPage(CSettingOptionPage::IDD)
    , m_dwManualPatchMinVer(100)    
    , m_OwnerSheet(ownerSheet)
    , m_pmSettingOption(pmSetting)
{    
    
}

CSettingOptionPage::~CSettingOptionPage()
{

}

void CSettingOptionPage::DoDataExchange(CDataExchange* pDX)
{
    CPropertyPage::DoDataExchange(pDX);

    DDX_Control(pDX, IDC_CB_OPT_PATCH_TYPE, m_cbPatchType);
    DDX_Control(pDX, IDC_ED_OPT_OLD_PKG, m_edOldPkgPos);
    DDX_Control(pDX, IDC_ED_OPT_NEW_CLIENT, m_edNewClientPos);
    DDX_Control(pDX, IDC_ED_OPT_NEW_PKG, m_edNewPkgPos);
    DDX_Control(pDX, IDC_ED_OPT_MAX_PKG, m_edMaxPkgSize);
    DDX_Control(pDX, IDC_CB_OPT_OLD_PKG_POS, m_cbPkgPos);
    DDX_Control(pDX, IDC_ED_OPT_FTP_ADDR, m_edFTPAddr);
    DDX_Control(pDX, IDC_ED_OPT_FTP_PORT, m_edFTPPort);
    DDX_Control(pDX, IDC_CK_OPT_FTP_PASSIVE, m_bFTPPassive);
    DDX_Control(pDX, IDC_ED_OPT_MANUAL_PATCH_FILE, m_edManualPatchFolder);
    DDX_Control(pDX, IDC_ED_OPT_MANUAL_SFX_FILE, m_edManualPatchSFXFile);
    DDX_Control(pDX, IDC_ED_OPT_MANUAL_MIN_VER, m_edManualPatchMinVer);

    DDX_Text(pDX, IDC_ED_OPT_MANUAL_MIN_VER, m_dwManualPatchMinVer);
    DDV_MinMaxUInt(pDX, m_dwManualPatchMinVer, 100, 10000);
}


BEGIN_MESSAGE_MAP(CSettingOptionPage, CPropertyPage)

    ON_BN_CLICKED(IDC_BTN_OPT_OLD_PKG, OnBnClickedBtnOptOldPkg)
    ON_BN_CLICKED(IDC_BTN_OPT_NEW_CLIENT, OnBnClickedBtnOptNewClient)
    ON_BN_CLICKED(IDC_BTN_OPT_NEW_PKG, OnBnClickedBtnOptNewPkg)
    ON_BN_CLICKED(IDC_BTN_OPT_MANUAL_PATCH_FILE, OnBnClickedBtnOptManualPatchFile)
    ON_BN_CLICKED(IDC_BTN_OPT_MANUAL_SFX_FILE, OnBnClickedBtnOptManualSfxFile)
    ON_BN_CLICKED(ID_SAVE_SETUP, OnBnClickedSaveSetup)
    ON_BN_CLICKED(ID_LOAD_SETUP, OnBnClickedLoadSetup)

    ON_REGISTERED_MESSAGE(PMConst::AP_SETTING_ENABLE,  OnEnableAutoPatchOption)
    ON_REGISTERED_MESSAGE(PMConst::AP_SETTING_DISABLE, OnDisableAutoPatchOption)
    ON_REGISTERED_MESSAGE(PMConst::MP_SETTING_ENABLE,  OnEnableManualPatchOption)
    ON_REGISTERED_MESSAGE(PMConst::MP_SETTING_DISABLE, OnDisableManualPatchOption)

    ON_CBN_SELCHANGE(IDC_CB_OPT_OLD_PKG_POS, OnCbnSelchangeCbOptOldPkgPos)
    ON_WM_DESTROY()
END_MESSAGE_MAP()


// CSettingOptionPage 메시지 처리기입니다.

inline int AddCBString(CComboBox& combo, CString& tempString, int nIndex, UINT nID)
{
    tempString.LoadString(nID);
    return combo.InsertString(nIndex, tempString);
}

BOOL CSettingOptionPage::OnInitDialog()
{
    CPropertyPage::OnInitDialog();

    // TODO:  여기에 추가 초기화 작업을 추가합니다.
    CString szTmp;
    
    m_cbPatchType.InsertString(0, PMConst::PatchType_Part1);    
    m_cbPatchType.InsertString(1, PMConst::PatchType_BattleLohan);
    m_cbPatchType.InsertString(2, PMConst::PatchType_Part2);
    m_cbPatchType.InsertString(3, PMConst::PatchType_Part2Test);
    m_cbPatchType.InsertString(4, PMConst::PatchType_Part2Malay);

    AddCBString(m_cbPkgPos, szTmp, 0, IDS_CB_FTP);
    AddCBString(m_cbPkgPos, szTmp, 1, IDS_CB_LOCAL);
    
    OnCbnSelchangeCbOptOldPkgPos();
    return TRUE;  // return TRUE unless you set the focus to a control
    // 예외: OCX 속성 페이지는 FALSE를 반환해야 합니다.
}

void CSettingOptionPage::OnBnClickedBtnOptOldPkg()
{
    // TODO: 여기에 컨트롤 알림 처리기 코드를 추가합니다.
    PMUtil::BrowseForFolder(GetSafeHwnd(), 
        _T("예전 패키지가 있는 폴더를 선택해주세요"), m_edOldPkgPos);
}

void CSettingOptionPage::OnBnClickedBtnOptNewClient()
{
    // TODO: 여기에 컨트롤 알림 처리기 코드를 추가합니다.
    PMUtil::BrowseForFolder(GetSafeHwnd(),  
        _T("깨끗한 클라이언트 파일이 있는 폴더를 선택해주세요"), m_edNewClientPos);
}

void CSettingOptionPage::OnBnClickedBtnOptNewPkg()
{
    // TODO: 여기에 컨트롤 알림 처리기 코드를 추가합니다.
    PMUtil::BrowseForFolder(GetSafeHwnd(), 
        _T("새 패키지 파일이 저장될 루트 폴더를 선택해주세요"), m_edNewPkgPos);
}

void CSettingOptionPage::OnBnClickedBtnOptManualPatchFile()
{
    // TODO: 여기에 컨트롤 알림 처리기 코드를 추가합니다.
    PMUtil::BrowseForFolder(GetSafeHwnd(), 
        _T("수동 패치 파일이 위치한 폴더를 선택해주세요"), m_edManualPatchFolder);
}

void CSettingOptionPage::OnBnClickedBtnOptManualSfxFile()
{
    // TODO: 여기에 컨트롤 알림 처리기 코드를 추가합니다.    
    CString szFileName;
    if (PMUtil::BrowseForExisingFile(this->GetSafeHwnd(),
        _T("수동 패치 SFX파일을 선택해주세요"), "SFX File\0*.exe", szFileName))
    {
        m_edManualPatchSFXFile.SetWindowText(szFileName);
    }
}


void CSettingOptionPage::OnBnClickedSaveSetup()
{
    // TODO: 여기에 컨트롤 알림 처리기 코드를 추가합니다.

    UpdateSetupData(TRUE);

    if (!m_pmSettingOption.SaveSetting())
    {
        MessageBox(_T("셋업 파일을 저장하기 위해서 여는 데 실패했습니다"), 
            _T("파일 열기 오류"), MB_OK | MB_ICONEXCLAMATION);
    }
}

void CSettingOptionPage::OnBnClickedLoadSetup()
{
    // TODO: 여기에 컨트롤 알림 처리기 코드를 추가합니다.
    if (m_pmSettingOption.LoadSetting())
    {
        UpdateSetupData(FALSE);
        OnCbnSelchangeCbOptOldPkgPos();
    }
    else
    {
        MessageBox(_T("셋업 파일을 불러오기 위해서 여는 데 실패했습니다"), 
            _T("파일 열기 오류"), MB_OK | MB_ICONEXCLAMATION);
    }
}

void SetCBSel(CComboBox& cb, CString& szValue, int nDefaultSel = 0)
{
    CString szCBValue;
    int nMaxCount = cb.GetCount();
    for (int nCount = 0; nCount < nMaxCount; ++nCount)
    {
        cb.GetLBText(nCount, szCBValue);

        if (0 == szValue.CompareNoCase(szCBValue))
        {
            cb.SetCurSel(nCount);
            break;
        }
    }

    if (nCount == nMaxCount)
    {
        // 찾아봐서 맞는 문자열이 없으면 기본값으로 선택
        cb.SetCurSel(nDefaultSel);
    }
}


void CSettingOptionPage::UpdateSetupData(bool bSaveAndValidate)
{
    CString szValue;

    struct KeyValuePair
    {
        LPCTSTR m_szKey;
        CEdit&  m_edValue;
    };

    KeyValuePair keyValueData[] = 
    {
        { PMConst::AP_OldPkg,    m_edOldPkgPos },
        { PMConst::AP_NewClient, m_edNewClientPos },
        { PMConst::AP_NewPkg,    m_edNewPkgPos },
        { PMConst::AP_MaxPkg,    m_edMaxPkgSize },
        { PMConst::AP_FTPAddr,   m_edFTPAddr },
        { PMConst::AP_FTPPort,   m_edFTPPort },
        { PMConst::MP_Folder,    m_edManualPatchFolder },
        { PMConst::MP_SFXFile,   m_edManualPatchSFXFile }
    };

    const int nMaxData = sizeof(keyValueData) / sizeof(KeyValuePair);

    if (!bSaveAndValidate)
    {
        // 셋업 맵의 데이터를 컨트롤로 저장한다.
        for (int nCount = 0; nCount < nMaxData; ++nCount)
        {
            m_pmSettingOption.GetSettingData(keyValueData[nCount].m_szKey, szValue);
            keyValueData[nCount].m_edValue.SetWindowText(szValue);
        }
            
        m_pmSettingOption.GetSettingData(PMConst::PatchType, szValue);
        SetCBSel(m_cbPatchType, szValue);

        m_pmSettingOption.GetSettingData(PMConst::AP_PkgPosType, szValue);
        SetCBSel(m_cbPkgPos, szValue);

        m_pmSettingOption.GetSettingData(PMConst::AP_FTPPassive, szValue);
        m_bFTPPassive.SetCheck(0 == szValue.CompareNoCase(_T("TRUE")) ? BST_CHECKED : BST_UNCHECKED);

        m_pmSettingOption.GetSettingData(PMConst::MP_MinVer, szValue);
        long nVersion = atol(szValue);
        if (nVersion < 100) { nVersion = 100; }
        m_dwManualPatchMinVer = nVersion;

        // 컨트롤 데이터를 화면에 반영한다.
        UpdateData(FALSE);
    }
    else
    {   
        // 화면 데이터를 컨트롤에 읽어온다.
        UpdateData(TRUE);

        // 컨트롤의 데이터를 셋업 맵에 저장한다.        
        for (int nCount = 0; nCount < nMaxData; ++nCount)
        {
            keyValueData[nCount].m_edValue.GetWindowText(szValue);
            m_pmSettingOption.SetSettingData(keyValueData[nCount].m_szKey, szValue);            
        }
    
        int nCurSel = m_cbPatchType.GetCurSel();
        if (CB_ERR != nCurSel)
        {
            m_cbPatchType.GetLBText(nCurSel, szValue);
            m_pmSettingOption.SetSettingData(PMConst::PatchType, szValue);
        }
        
        nCurSel = m_cbPkgPos.GetCurSel();
        if (CB_ERR != nCurSel)
        {
            m_cbPkgPos.GetLBText(nCurSel, szValue);
            m_pmSettingOption.SetSettingData(PMConst::AP_PkgPosType, szValue);
        }

        m_pmSettingOption.SetSettingData(PMConst::AP_FTPPassive, 
            BST_CHECKED == m_bFTPPassive.GetCheck() ? _T("TRUE") : _T("FALSE"));

        szValue.Format("%u", m_dwManualPatchMinVer);
        m_pmSettingOption.SetSettingData(PMConst::MP_MinVer, szValue);
    }
}

bool CSettingOptionPage::IsEmptyOption()
{
    if (CB_ERR == m_cbPatchType.GetCurSel() ||
        0 == m_edOldPkgPos.GetWindowTextLength() ||
        0 == m_edNewClientPos.GetWindowTextLength() ||
        0 == m_edNewPkgPos.GetWindowTextLength() ||
        0 == m_edMaxPkgSize.GetWindowTextLength() ||
        CB_ERR == m_cbPkgPos.GetCurSel() || 
        0 == m_edManualPatchFolder.GetWindowTextLength() ||
        0 == m_edManualPatchSFXFile.GetWindowTextLength() ||
        m_dwManualPatchMinVer < 100 ||
        10000 < m_dwManualPatchMinVer)
    {
        // 빈 항목이 있으면 실패!
        return true;
    }

    CString szPkgPos, szFTPPos((LPCTSTR)IDS_CB_FTP);
    m_cbPkgPos.GetLBText(m_cbPkgPos.GetCurSel(), szPkgPos);

    if (0 == szPkgPos.CompareNoCase(szFTPPos) &&
        (0 == m_edFTPAddr.GetWindowTextLength() ||
         0 == m_edFTPPort.GetWindowTextLength()))
    {
        // FTP를 선택했는데, 주소나 Port가 없으면 실패!
        return true;
    }

    return false;
}

BOOL CSettingOptionPage::OnKillActive()
{
    // TODO: 여기에 특수화된 코드를 추가 및/또는 기본 클래스를 호출합니다.
    
    if (this == m_OwnerSheet.GetActivePage())
    {
        // 페이지를 옮기면 자동으로 저장됨
        SendMessage(WM_COMMAND, MAKEWPARAM(ID_SAVE_SETUP, BN_CLICKED));
        
        if (IsEmptyOption())
        {
            MessageBox(_T("기록하지 않은 설정이 있습니다. 남은 설정을 모두 입력해 주십시오"), 
                _T("옵션 설정"), MB_OK | MB_ICONEXCLAMATION);

            return FALSE;
        }
    }

    return CPropertyPage::OnKillActive();
}

BOOL CSettingOptionPage::OnSetActive()
{
    // TODO: 여기에 특수화된 코드를 추가 및/또는 기본 클래스를 호출합니다.
    SendMessage(WM_COMMAND, MAKEWPARAM(ID_LOAD_SETUP, BN_CLICKED));
    return CPropertyPage::OnSetActive();
}


afx_msg LRESULT CSettingOptionPage::OnEnableAutoPatchOption(WPARAM wParam, LPARAM lParam)
{
    SetAutoPatchOption(true);
    return 0;
}

afx_msg LRESULT CSettingOptionPage::OnDisableAutoPatchOption(WPARAM wParam, LPARAM lParam)
{
    SetAutoPatchOption(false);
    return 0;
}

afx_msg LRESULT CSettingOptionPage::OnEnableManualPatchOption(WPARAM wParam, LPARAM lParam)
{
    SetManualPatchOption(true);
    return 0;
}

afx_msg LRESULT CSettingOptionPage::OnDisableManualPatchOption(WPARAM wParam, LPARAM lParam)
{
    SetManualPatchOption(false);
    return 0;
}

void CSettingOptionPage::SetAutoPatchOption(bool bEnable)
{
    UINT nDisableID[] = 
    {
        IDC_BTN_OPT_OLD_PKG,
        IDC_BTN_OPT_NEW_CLIENT,
        IDC_BTN_OPT_NEW_PKG,
    };

    PMUtil::EnableDlgItems(*this, nDisableID, 
        sizeof(nDisableID)/sizeof(UINT), bEnable);

    if (bEnable && !theApp.IsManualPatchOperate())
    {
        // 수동패치가 작동 안할때만 Enable
        m_cbPatchType.EnableWindow(TRUE);
    }
    else
    {
        m_cbPatchType.EnableWindow(FALSE);
    }

    m_cbPkgPos.EnableWindow(bEnable);
    m_bFTPPassive.EnableWindow(bEnable);

    m_edOldPkgPos.SetReadOnly(!bEnable);
    m_edMaxPkgSize.SetReadOnly(!bEnable);
   
    m_edFTPAddr.SetReadOnly(!bEnable);
    m_edFTPPort.SetReadOnly(!bEnable);
}

void CSettingOptionPage::SetManualPatchOption(bool bEnable)
{
    UINT nDisableID[] = 
    {
        IDC_BTN_OPT_MANUAL_PATCH_FILE,
        IDC_BTN_OPT_MANUAL_SFX_FILE
    };

    PMUtil::EnableDlgItems(*this, nDisableID, 
        sizeof(nDisableID)/sizeof(UINT), bEnable);

    if (bEnable && !theApp.IsAutoPatchOperate())
    {
        // 자동패치가 작동 안할때만 Enable
        m_cbPatchType.EnableWindow(TRUE);
    }
    else
    {
        m_cbPatchType.EnableWindow(FALSE);
    }

    m_edManualPatchMinVer.SetReadOnly(!bEnable);
}

void CSettingOptionPage::OnCbnSelchangeCbOptOldPkgPos()
{
    // TODO: 여기에 컨트롤 알림 처리기 코드를 추가합니다.
        
    BOOL bEnableFTP = FALSE;

    int nCurSel = m_cbPkgPos.GetCurSel();
    if (CB_ERR != nCurSel)
    {
        CString szFTP((LPCTSTR)IDS_CB_FTP);
        CString szCurrentSel;
        m_cbPkgPos.GetLBText(nCurSel, szCurrentSel);

        if (0 == szCurrentSel.CompareNoCase(szFTP))
        {
            bEnableFTP = TRUE;
        }
    }

    m_edFTPAddr.EnableWindow(bEnableFTP);
    m_edFTPPort.EnableWindow(bEnableFTP);
    m_bFTPPassive.EnableWindow(bEnableFTP);

    m_edOldPkgPos.SetReadOnly(!bEnableFTP);
}


void CSettingOptionPage::OnDestroy()
{
    SendMessage(WM_COMMAND, MAKEWPARAM(ID_SAVE_SETUP, BN_CLICKED));
    CPropertyPage::OnDestroy();    
}
