#include <afxwin.h>
#include <stdlib.h>
#include <time.h>
#include <ctype.h>
#include "resource.h"
#include "roll.h"
#include "critical.h"
#include "spell1.h"
#include "CSpellBook.h"
#include "main.h"

#define  NOPOS	-1

BEGIN_MESSAGE_MAP(CRollDice,CDialog)
	ON_WM_VSCROLL()
	ON_EN_CHANGE(IDC_NUMDICE, OnDiceNum)
	ON_BN_CLICKED(IDB_ROLL, OnDiceRoll)
	ON_BN_CLICKED(IDB_CLEAR, OnDiceReset)
	ON_BN_CLICKED(IDB_CRITICAL, OnCriticalHit)
	ON_BN_CLICKED(ID_OK, OnCancel)
	ON_LBN_DBLCLK(IDC_LIST1, OnCriticalHit)
	ON_LBN_SELCHANGE(IDC_LIST1, OnCHButton)
END_MESSAGE_MAP()

// Funzioni membro di CRollDice

CRollDice::CRollDice()
{
	Create(IDD_ROLLDICE);
	SetIcon(AfxGetApp()->LoadIcon(IDI_ICON2),TRUE);
	SetWindowText("Dice Roller");
}

BOOL CRollDice::OnInitDialog()
{
	CDialog::OnInitDialog();

	CtrlEdit()->SetWindowText("1");
	CheckRadioButton(IDC_RADIO1, IDC_RADIO8, IDC_RADIO1+ 2); // posiziona d20 iniziale
	m_DicetoRoll=20;

	srand( (unsigned)time( NULL ) );
	return TRUE;
}

void CRollDice::OnDiceNum()
{
	CEdit *EditNum= CtrlEdit();
	CString stringa;
	EditNum->GetWindowText(stringa);
	m_NumofDice=atoi(stringa);

	if(m_NumofDice<0)
		m_NumofDice=0;

	CtrlButton(IDB_ROLL).EnableWindow(m_NumofDice);
}

void CRollDice::OnDiceRoll()
{
	int totale=0;
	char tmp[100];
	if(m_NumofDice<=0)
		return;
	m_GetDicetoRoll();

	int lanci=0;
	CListBox * pList= CtrlListBox();
	pList->ResetContent();

	while(lanci++ < m_NumofDice)
	{
		int errore;
		CString stringa;
		stringa=_itoa(lanci,tmp,10);
		stringa+="		    ";
		int risult=m_GetRandomNumber();
		stringa+=_itoa(risult,tmp,10);
		totale+=risult;
		if( risult >= 18 && m_DicetoRoll==20)
			stringa+="\t    C";
		errore = pList->AddString(stringa);
		if (errore==LB_ERR || errore==LB_ERRSPACE)
		{
			CString stringa;
			if (errore==LB_ERR)
				stringa="Errore occorso durante la creazione di una nuova voce!";
			else
				stringa="Errore: insufficiente spazio per memorizzare la nuova stringa!";
			CtrlEdit()->SetWindowText(itoa(lanci-1, tmp, 10));
			MessageBox(stringa, "Errore: CListBox.", MB_OK|MB_ICONSTOP);
			break;
		}
	}
	CtrlButton(IDB_CLEAR).EnableWindow(TRUE);
	CtrlTotal().SetWindowText(itoa(totale, tmp, 10));
}

void CRollDice::OnDiceReset()
{
	CtrlEdit()->SetWindowText("");
	CtrlListBox()->ResetContent();
	CtrlButton(IDB_CLEAR).EnableWindow(FALSE);
	CtrlButton(IDB_CRITICAL).EnableWindow(TRUE);
	CtrlEdit()->SetFocus();
}

void CRollDice::OnCriticalHit()
{
	CListBox * pList= CtrlListBox();
	CString stringa;
	int position=NOPOS;
	int Roll;

	m_CriticalSel= pList->GetCurSel();
	if (m_CriticalSel == LB_ERR || pList->GetCount() ==LB_ERR)
	{
		CDialogRollExt DlgRE (this);
		if (DlgRE.DoModal()==IDOK)
			Roll=DlgRE.m_roll;
		else
			return;
	}
	else
	{
		CString stringatmp;
		pList->GetText(m_CriticalSel, stringa);
		position=stringa.Find('C');
		if (position == -1)
			return;
		int cont=0;
		while (stringa[cont]!='\t')
			cont++;
		cont+=6;
		while (isdigit(stringa[cont]))
			stringatmp+=stringa.GetAt(cont++);
		Roll=atoi(stringatmp);
	}

	CDialogCH DlgCH (this);
	if ( DlgCH.DoModal() == IDOK )
	{
		DlgCH.m_Calculate(Roll);

		CDialogCritical DlgC (this);

		DlgC.m_riga1=DlgCH.GetRiga1();
		DlgC.m_riga2=DlgCH.GetRiga2();
		DlgC.m_riga3=DlgCH.GetRiga3();

		DlgC.DoModal();

		if (position!= NOPOS)
		{
			stringa.SetAt(position,'c');
			pList->DeleteString(m_CriticalSel);
			pList->InsertString(m_CriticalSel,stringa);
			pList->Invalidate();
		}
	}
}

void CRollDice::OnVScroll( UINT Code, UINT Pos, CScrollBar* pScrollBar )
{
	CEdit *EditNum= CtrlEdit();
	CString stringa;
	char tmp[100];
	EditNum->GetWindowText(stringa);
	m_NumofDice=atoi(stringa);

	int variazione;

	if(Code==SB_LINEUP)
		variazione=1;
	else if(Code==SB_LINEDOWN)
		variazione=-1;
	else
		return;

	m_NumofDice += variazione;
	if (m_NumofDice <= 0)
		m_NumofDice=1;

	EditNum->SetWindowText(_itoa(m_NumofDice, tmp, 10));
}

void CRollDice::OnCHButton()
{
	CString stringa;

	CListBox * pList= CtrlListBox();
	m_CriticalSel= pList->GetCurSel();
	if (m_CriticalSel!=LB_ERR)
	{
		pList->GetText(m_CriticalSel, stringa);
		if (stringa.Find('C')== -1)
			CtrlButton(IDB_CRITICAL).EnableWindow(FALSE);
		else
			CtrlButton(IDB_CRITICAL).EnableWindow(TRUE);
	}
}

void CRollDice::OnCancel()
{
	DestroyWindow();
}

void CRollDice::PostNcDestroy()
{
	((CMainWindow *) AfxGetMainWnd())->m_Roll = NULL;
	delete this;
}

// Funzioni private della classe

int CRollDice::m_GetRandomNumber()
{
//	int gap=(rand()%m_DicetoRoll);
//	while(gap--)
//		rand();
	return (rand()%m_DicetoRoll)+1;
}

void CRollDice::m_GetDicetoRoll()
{
	int index=IDC_RADIO8-IDC_RADIO1;

	while (((CButton *) GetDlgItem(IDC_RADIO1+index)) -> GetCheck() == 0 && index >0)
		index--;
	switch(index)
	{
	case 0: m_DicetoRoll= 100;
		break;
	case 1: m_DicetoRoll= 30;
		break;
	case 2: m_DicetoRoll= 20;
		break;
	case 3: m_DicetoRoll= 12;
		break;
	case 4: m_DicetoRoll= 10;
		break;
	case 5: m_DicetoRoll= 8;
		break;
	case 6: m_DicetoRoll= 6;
		break;
	case 7: m_DicetoRoll= 4;
		break;

	default: m_DicetoRoll= 0;
	}
}

// Definizione funzioni per classe CDialogCH
BEGIN_MESSAGE_MAP(CDialogCH, CDialog)
	ON_CBN_SELCHANGE(IDC_CTARGET2, OnSetLocation)
END_MESSAGE_MAP()

BOOL CDialogCH::OnInitDialog()
{
	CDialog::OnInitDialog();

	m_THACO=20;
	m_AC=4;
	m_BonusHit=0;
	m_BonusDamage=0;
	m_SavingThrowDeath=16;
	m_TargetSize=2;
	m_Weapon=0;
	m_LocationHit=0;
	m_Target=0;
	m_CWeapon.m_FillList( *(CComboBox*) GetDlgItem(IDC_CWEAPON));

	UpdateData(FALSE);
	return TRUE;
}

void CDialogCH::OnSetLocation()
{
	UpdateData();
	
	//inserimento stringhe generali
	CComboBox * pCBptr = ((CComboBox *) GetDlgItem(IDC_CLOCATION));
	pCBptr->ResetContent();
	pCBptr->AddString("General");
	pCBptr->AddString("Low Attacks");
	pCBptr->AddString("High Attacks");

	//inserimento voci dipendenti da target
	CString base = "Call Shot - ";
	CString riga;
	for(int cont=0; cont<10; cont++)
	{
		CString tmp;
		riga = base;
		tmp.LoadString(m_TableCritical.GetLocationDamage(m_Target, cont));
		riga+=tmp;
		pCBptr->AddString(riga);
		pCBptr->EnableWindow();
	}
}

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

	DDX_Text(pDX, IDC_ETHAC0, m_THACO);
	DDV_MinMaxInt(pDX, m_THACO, 2, 20);
	DDX_Text(pDX, IDC_EAC, m_AC);
	DDV_MinMaxInt(pDX, m_AC, -10, 10);
	DDX_Text(pDX, IDC_EBONUS, m_BonusHit);
	DDV_MinMaxInt(pDX, m_BonusHit, 0 , 20);
	DDX_Text(pDX, IDC_EDAMAG, m_BonusDamage);
	DDV_MinMaxInt(pDX, m_BonusDamage, 0, 25);
	DDX_Text(pDX, IDC_EST, m_SavingThrowDeath);
	DDV_MinMaxInt(pDX, m_SavingThrowDeath, 2, 20);
	DDX_CBIndex(pDX, IDC_CTARGET, m_TargetSize);
	DDX_CBIndex(pDX, IDC_CWEAPON, m_Weapon);
	DDX_CBIndex(pDX, IDC_CLOCATION, m_LocationHit);
	DDX_CBIndex(pDX, IDC_CTARGET2, m_Target);
}

void CDialogCH::m_Calculate(int tiro)
{
	int soglia=m_THACO-m_AC-m_BonusHit+5;
	int Damage;		// risultato dei danni
	int dado;		// dado da usare per danni
	int bonus;		// bonus per danni per arma selez
	int moltip_danni =1;	// tiene nota del moltiplic danni

	// Calcolo Normale dei danni
	int Danni = S_M;
	if (m_TargetSize > 3)		// Target Size > L
		Danni = L;
	m_CWeapon.GetDamage(m_Weapon, Danni, dado, bonus);
	Damage = (rand()%dado) +1  + bonus;

	if (tiro >= soglia)
	{
		moltip_danni=2;

		if ((rand()%20)+1 < m_SavingThrowDeath)
		{
			// Selezione primo parametro Tabella critici - selezione tabella
			int PrimoParam = m_TableCritical.GetTable(m_CWeapon.GetTypeDamage(m_Weapon), m_Target);
			int locazioneColpo;

			// Selezione locazione (10 posizioni)
			switch (m_LocationHit)
			{
			case 0 :	// Colpo normale
				locazioneColpo = rand()%10;
				break;
			
			case 1 :	// Colpo Basso
				locazioneColpo = rand()%6 ;
				break;

			case 2 :	// Colpo Alto
				locazioneColpo = rand()%6 +4;
				break;

			default:	// Colpo mirato
				locazioneColpo = m_LocationHit - 3;
			}

			// selezione locazione
			int SecondoParam=m_TableCritical.GetLocation(locazioneColpo);

			// selezione danno
			int TerzoParam;
			int diff= m_TargetSize-m_CWeapon.GetSize(m_Weapon);
			
			// implico nel calcolo dei dadi la riduzione di 1 per il calcolo della tabella

			if (diff==1)		// Arma stessa dimensione del bersaglio
				TerzoParam=rand()%4 + rand()%4 + 2;
			else
				if (diff==0)	// Arma di una grandezza piu' grande
					TerzoParam=rand()%6 + rand()%6+2;
				else
					if (diff>1)	// Bersaglio piu' grande
						TerzoParam=rand()%6+1;
					else
						if (diff<0)	// arma due volte piu' grande
							TerzoParam=rand()%8 + rand()%8 + 2;

			if(TerzoParam>11)
			{
				TerzoParam=11;
				moltip_danni=3;
			}

			Riga2.LoadString(m_TableCritical.GetLocationDamage(m_Target, locazioneColpo));
			Riga3 = m_TableCritical.GetDamage(PrimoParam, SecondoParam, TerzoParam);
		}
	}
	else
		Riga2=" --";

	char tmp[10];
	Riga1=_itoa((Damage*moltip_danni) + m_BonusDamage, tmp, 10);
}

CString CDialogCH::GetRiga1()
{
	return Riga1;
}

CString CDialogCH::GetRiga2()
{
	return Riga2;
}

CString CDialogCH::GetRiga3()
{
	return Riga3;
}

// Funzioni classe CDialogRollExt

BOOL CDialogRollExt::OnInitDialog()
{
	CDialog::OnInitDialog();

	m_roll=18;
	UpdateData(FALSE);
	
	CEdit *pEdit = (CEdit*)GetDlgItem(IDC_EXTROLL);
	pEdit->SetFocus();
	pEdit->SetSel(DWORD(-1<<16));
	return FALSE;
}

void CDialogRollExt::DoDataExchange(CDataExchange *pDX)
{
	DDX_Text(pDX, IDC_EXTROLL, m_roll);
	DDV_MinMaxInt(pDX, m_roll, 1, 20);
}