// ScriptRunner.cpp: implementation of the CScriptRunner class.
//


#include "stdafx.h"
#include "ScriptRunner.h"
#include "Board.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction


CScriptRunner::CScriptRunner()
	: m_pChip(nullptr)
	, m_lpszAscii(nullptr)
	, m_nScriptLinePos(0)
	, m_nScriptCurrTick(0)
	, m_nScriptStartDelay(SCRIPT_START_DELAY)
	, m_bRus(false)
	, m_bIsAr2Press(false)
	, m_bHasScript(false)
{
}

CScriptRunner::~CScriptRunner()
{
	SAFE_DELETE_ARRAY(m_lpszAscii);
}


void CScriptRunner::SetScriptPath(const CString &strScriptPath, const CString &strScriptFileName)
{
	if (m_fileScript.m_pStream)
	{
		m_fileScript.Close();
	}

	m_strScriptsPath = strScriptPath;
	m_strScriptFileName = strScriptFileName;
	m_bHasScript = !m_strScriptFileName.IsEmpty();
	m_strScriptLine = _T("");
}


bool CScriptRunner::RunScript()
{
	ASSERT(m_pChip);

	if (!m_bHasScript)
	{
		return false;    // Если скрипт не задан, выйдем с ошибкой
	}

	if (!m_pChip) // Если нету эмулируемого устройства, выйдем с ошибкой
	{
		return false;
	}

	if (!m_fileScript.m_pStream) //если файл ещё не открыт, поробуем открыть
	{
		CString ofn = m_strScriptsPath + m_strScriptFileName;

		// если файл не открыт, откроем его
		if (!m_fileScript.Open(ofn, CFile::modeRead))
		{
			// Если файл скрипта не открывается, то реинициализируем обработчик
			// и выйдем с ошибкой
			m_strScriptFileName.Empty();
			m_bHasScript = false;
			return false;
		}

		// Если скрипт открылся, инициализируем переменные
		m_strScriptLine = _T("");
		m_nScriptLinePos = 0;
		m_nScriptCurrTick = GetTickCount(); // Запускаем таймер
	}

	// Если скрипт открыт и всё в порядке
	// Ждём определённое время перед запуском скрипта
	if ((GetTickCount() - m_nScriptCurrTick) / 1000 < m_nScriptStartDelay)
	{
		return true;
	}

	if (m_nScriptLinePos >= m_strScriptLine.GetLength())
	{
		// Если дошли до конца текущей строки,
		// почитаем следующую
		m_nScriptLinePos = 0;
		SAFE_DELETE_ARRAY(m_lpszAscii);

		if (!m_fileScript.ReadString(m_strScriptLine))
		{
			// Если строки закончились,
			// закроем файл и переинициализируем переменные
			SetScriptPath(_T(""), _T(""));
			return false;
		}

		m_strScriptLine += _T('\n'); // добавим перевод каретки в конец строки
		int sizeOfString = (m_strScriptLine.GetLength() + 1);
		m_lpszAscii = new char[sizeOfString];
		WideCharToMultiByte(CP_ACP, 0, m_strScriptLine, -1, m_lpszAscii, sizeOfString, nullptr, nullptr);
	}

	if (!m_strScriptLine.IsEmpty()) // Если строка не пуста
	{
		// Передадим новый символ только если регистр БК 177660 готов
		// т.е. ждём, пока БК прочтёт следующий код из 177662
		if ((m_pChip->m_reg177660 & 0200) == 0 && !m_pChip->GetPSWBit(PSW_P_POS))
		{
			ParseNextChar(m_lpszAscii[m_nScriptLinePos++]);
		}
	}

	return true;
}


void CScriptRunner::ParseNextChar(unsigned char ansi_ch)
{
	if (ansi_ch == '|')
	{
		//это снова надо установить задержку
		m_nScriptCurrTick = GetTickCount();
		return;
	}
	else if (ansi_ch >= 192 && !m_bRus)
	{
		m_nScriptLinePos--;
		ansi_ch = BKKEY_RUS;
		m_bRus = true;
	}
	else if (ansi_ch >= 32 && ansi_ch <= 127 && m_bRus)
	{
		m_nScriptLinePos--;
		ansi_ch = BKKEY_LAT;
		m_bRus = false;
	}

	SendNewCharToBK(ansi_ch);
}


void CScriptRunner::SendNewCharToBK(unsigned char ch)
{
	ANSIToBK(ch);  // Конвертируем символ в БКшную кодировку
	// Получим текущее состояние регистра
	WORD reg177660 = m_pChip->m_reg177660;
	// Установим состояние готовности в 177660
	m_pChip->m_reg177660 |= 0200;
	// Отправим код символа в 177662
	m_pChip->m_reg177662in = ch & 0177;
	// Установим флаг нажатия клавиши в 177716
	m_pChip->m_reg177716in &= ~0100;

	if (!m_bIsAr2Press)
	{
		m_pChip->KeyboardInterrupt(INTERRUPT_60);
	}
	else
	{
		m_pChip->KeyboardInterrupt(INTERRUPT_274);
	}
}
