
local event = require("event")
local modemConnection = require("modemConnection")
local ecs = require("ECSAPI")
local fs = require("filesystem")
local serialization = require("serialization")
local buffer = require("doubleBuffering")
local context = require("context")
local image = require("image")
local unicode = require("unicode")
local component = require("component")
local computer = require("computer")

-------------------------------------------------------------------------------------------------------------------------------

if not component.isAvailable("modem") then ecs.error("This program requires wireless modem to work!"); return end

local colors = {
	leftBar = 0x262626,
	leftBarSelection = 0x00A8FF,
	leftBarAlternative = 0x383838,
	leftBarText = 0xFFFFFF,
	leftBarSelectionText = 0xFFFFFF,
	leftBarSearchButton = 0x555555,
	leftBarSearchButtonText = 0xFFFFFF,

	scrollBar = 0xCCCCCC,
	scrollBarPipe = 0x666666,

	topBar = 0xEEEEEE,
	topBarName = 0x000000,
	topBarAddress = 0x555555,

	topMenu = 0xFFFFFF,

	chatZone = 0xFFFFFF,
	senderCloudColor = 0x3392FF,
	senderCloudTextColor = 0xFFFFFF,
	yourCloudColor = 0x55BBFF,
	yourCloudTextColor = 0xFFFFFF,
	systemMessageColor = 0x555555,

	sendButtonColor = 0x555555,
	sendButtonTextColor = 0xFFFFFF,

	messageInputBarColor = 0xEEEEEE,
	messageInputBarInputBackgroundColor = 0xFFFFFF,
	messsageInputBarButtonColor = 0x3392FF,
	messsageInputBarButtonTextColor = 0xFFFFFF,
	messsageInputBarTextColor = 0x262626,
}

local chatHistory = {}
local avatars = {}
local port = 899
local modem = component.modem
modem.open(port)

-------------------------------------------------------------------------------------------------------------------------------

local pathToApplication = "/MineOS/Applications/Chat.app/"
local pathToSaveSendedFiles = "/MineOS/Downloads/"
local contactsAvatarsPath = pathToApplication .. "Resources/Avatars/"
local personalAvatarPath = contactsAvatarsPath .. "MyAvatar.pic"
local chatHistoryPath = "MineOS/System/Chat/History.cfg"
local avatarWidthLimit = 6
local avatarHeightLimit = 3

local currentChatID = 1
local currentChatMessage = 1
local currentMessageText

buffer.start()
local messageInputHeight = 5
local leftBarHeight = buffer.screen.height - 9
local leftBarWidth = math.floor(buffer.screen.width * 0.2)
local chatZoneWidth = buffer.screen.width - leftBarWidth
local heightOfTopBar = 2 + avatarHeightLimit
local yLeftBar = 2 + heightOfTopBar
local chatZoneX = leftBarWidth + 1
local bottom
local chatZoneHeight = buffer.screen.height - yLeftBar - messageInputHeight + 1
local cloudWidth = chatZoneWidth - 2 * (avatarWidthLimit + 9)
local cloudTextWidth = cloudWidth - 4
local yMessageInput = buffer.screen.height - messageInputHeight + 1
local sendButtonWidth = 7
local messageInputWidth = chatZoneWidth - sendButtonWidth - 6

-------------------------------------------------------------------------------------------------------------------------------

--Объекты для тача
local obj = {}
local function newObj(class, name, ...)
	obj[class] = obj[class] or {}
	obj[class][name] = {...}
end

local function saveChatHistory()
	fs.makeDirectory(fs.path(chatHistoryPath) or "")
	local file = io.open(chatHistoryPath, "w")
	file:write(serialization.serialize(chatHistory))
	file:close()
end

local function loadChatHistory()
	if fs.exists(chatHistoryPath) then
		local file = io.open(chatHistoryPath, "r")
		chatHistory = serialization.unserialize(file:read("*a"))
		file:close()
	else
		chatHistory = {myName = "Аноним №" .. math.random(1, 1000)}
		saveChatHistory()
	end
end

local function loadAvatarFromFile(path)
	local avatar = 	image.load(path)
	local widthDifference = avatar.width - avatarWidthLimit
	local heightDifference = avatar.height - avatarHeightLimit

	if widthDifference > 0 then
		avatar = image.crop(avatar, "fromRight", widthDifference)
	end
	if heightDifference > 0 then
		avatar = image.crop(avatar, "fromBottom", heightDifference)
	end
	
	return avatar
end

local function loadPersonalAvatar()
	avatars.personal = loadAvatarFromFile(personalAvatarPath)
end

local function loadContactAvatar(ID)
	avatars.contact = loadAvatarFromFile(contactsAvatarsPath .. ID .. ".pic")
end

local function saveContactAvatar(ID, data)
	local file = io.open(contactsAvatarsPath .. ID .. ".pic", "w")
	file:write(data)
	file:close()
end

local function switchToContact(ID)
	currentChatID = ID
	currentChatMessage = #chatHistory[currentChatID]
	loadContactAvatar(currentChatID)
	chatHistory[currentChatID].unreadedMessages = nil
end

local function drawLeftBar()
	buffer.square(1, yLeftBar, leftBarWidth, leftBarHeight, colors.leftBar, 0xFFFFFF, " ")

	local howMuchContactsCanBeShown = math.floor(leftBarHeight / 3)
	obj.Contacts = {}

	local yPos = yLeftBar
	local counter = 1
	local text, textColor
	
	for i = 1, #chatHistory do
		textColor = colors.leftBarText
	
		--Рисуем подложку
		if i == currentChatID then
			buffer.square(1, yPos, leftBarWidth, 3, colors.leftBarSelection, 0xFFFFFF, " ")
			textColor = 0xFFFFFF
		elseif counter % 2 ~= 0 then
			buffer.square(1, yPos, leftBarWidth, 3, colors.leftBarAlternative, 0xFFFFFF, " ")
		end

		--Создаем объекты для клика
		newObj("Contacts", i, 1, yPos, leftBarWidth, yPos + 2)

		--Рендерим корректное имя
		text = chatHistory[i].name or address
		text = ecs.stringLimit("end", text, leftBarWidth - 4)

		--Рисуем имя
		yPos = yPos + 1
		buffer.text(2, yPos, textColor, text)
		
		--Если имеются непрочитанные сообщения, то показать их
		if chatHistory[i].unreadedMessages then
			local stringCount = tostring(chatHistory[i].unreadedMessages)
			local stringCountLength = unicode.len(stringCount)
			local x = leftBarWidth - 3 - stringCountLength
			buffer.square(x, yPos, stringCountLength + 2, 1, colors.leftBarText, 0xFFFFFF, " ")
			buffer.text(x + 1, yPos, colors.leftBar, stringCount)
		end

		yPos = yPos + 2
		counter = counter + 1
		if counter > howMuchContactsCanBeShown or yPos > buffer.screen.height then
			break
		end
	end

	--Кнопочка поиска юзеров
	obj.search = {buffer.button(1, buffer.screen.height - 2, leftBarWidth, 3, colors.leftBarSearchButton, colors.leftBarSearchButtonText, "Поиск")}
end

local function drawTopBar()
	buffer.square(1, 2, buffer.screen.width, heightOfTopBar, colors.topBar, 0xFFFFFF, " ")

	buffer.image(3, 3, avatars.personal)
	buffer.text(11, 3, colors.topBarName, chatHistory.myName)
	buffer.text(11, 4, colors.topBarAddress, modemConnection.localAddress)
end

local function drawTopMenu()
	obj.TopMenu = buffer.menu(1, 1, buffer.screen.width, colors.topMenu, 0, {"Чат", 0x000099}, {"История", 0x000000}, {"О программе", 0x000000})
end

local function drawEmptyCloud(x, y, cloudWidth, cloudHeight, cloudColor, fromYou)
	local upperPixel = "▀"
	local lowerPixel = "▄"

	--Рисуем финтифлюшечки
	if not fromYou then
		buffer.set(x, y - cloudHeight + 2, colors.chatZone, cloudColor, upperPixel)
		buffer.set(x + 1, y - cloudHeight + 2, cloudColor, 0xFFFFFF, " ")
		x = x + 2
	else
		buffer.set(x + cloudWidth + 3, y - cloudHeight + 2, colors.chatZone, cloudColor, upperPixel)
		buffer.set(x + cloudWidth + 2, y - cloudHeight + 2, cloudColor, 0xFFFFFF, " ")
	end

	--Заполняшечки
	buffer.square(x + 1, y - cloudHeight + 1, cloudWidth, cloudHeight, cloudColor, 0xFFFFFF, " ")
	buffer.square(x, y - cloudHeight + 2, cloudWidth + 2, cloudHeight - 2, cloudColor, 0xFFFFFF, " ")
	
	--Сгругленные краешки
	buffer.set(x, y - cloudHeight + 1, colors.chatZone, cloudColor, lowerPixel)
	buffer.set(x + cloudWidth + 1, y - cloudHeight + 1, colors.chatZone, cloudColor, lowerPixel)
	buffer.set(x, y, colors.chatZone, cloudColor, upperPixel)
	buffer.set(x + cloudWidth + 1, y, colors.chatZone, cloudColor, upperPixel)

	return y - cloudHeight + 1
end

local function drawTextCloud(x, y, cloudColor, textColor, fromYou, text)
	local y = drawEmptyCloud(x, y, cloudTextWidth, #text + 2, cloudColor, fromYou)
	x = fromYou and x + 2 or x + 4

	for i = 1, #text do
		buffer.text(x, y + i, textColor, text[i])
	end

	return y
end

local function drawFileCloud(x, y, cloudColor, textColor, fromYou, fileName)
	local y = drawEmptyCloud(x, y, 14, 8, cloudColor, fromYou)
	x = fromYou and x + 2 or x + 4

	ecs.drawOSIcon(x, y + 1, fileName, true, textColor)

	return y
end

local function stringWrap(text, limit)
	local strings = {}
	local textLength = unicode.len(text)
	local subFrom = 1
	while subFrom <= textLength do
		table.insert(strings, unicode.sub(text, subFrom, subFrom + limit - 1))
		subFrom = subFrom + limit
	end
	return strings
end

local function drawChat()

	local x, y = chatZoneX, yLeftBar
	buffer.square(x, y, chatZoneWidth, chatZoneHeight, colors.chatZone, 0xFFFFFF, " ")

	--Если отстутствуют контакты, то отобразить стартовое сообщение
	if not chatHistory[currentChatID] then
		local text = ecs.stringLimit("start", "Добавьте контакты с помощью кнопки \"Поиск\"", chatZoneWidth - 2)
		local x, y = math.floor(chatZoneX + chatZoneWidth / 2 - unicode.len(text) / 2), math.floor(yLeftBar + chatZoneHeight / 2)
		buffer.text(x, y, 0x555555, text)
		return
	end

	-- Ставим ограничение отрисовки буфера, чтобы облачка сообщений не ебошили
	-- За края верхней зоны чатзоны, ну ты понял, да?
	buffer.setDrawLimit(x, y, chatZoneWidth, chatZoneHeight)

	-- Стартовая точка
	y = buffer.screen.height - messageInputHeight - 1
	local xYou, xSender = x + 2, buffer.screen.width - 8
	-- Отрисовка облачков
	for i = currentChatMessage, 1, -1 do
		--Если не указан тип сообщения, то ренедрим дефолтные облачка
		if not chatHistory[currentChatID][i].type then
			--Если сообщенька от тебя, то цвет меняем
			if chatHistory[currentChatID][i].fromYou then
				y = drawTextCloud(xSender - cloudWidth - 2, y, colors.yourCloudColor, colors.yourCloudTextColor, chatHistory[currentChatID][i].fromYou, stringWrap(chatHistory[currentChatID][i].message, cloudTextWidth - 2))
				buffer.image(xSender, y, avatars.personal)
			else
				y = drawTextCloud(xYou + 8, y, colors.senderCloudColor, colors.senderCloudTextColor, chatHistory[currentChatID][i].fromYou, stringWrap(chatHistory[currentChatID][i].message, cloudTextWidth))
				buffer.image(xYou, y, avatars.contact)
			end
		--Если сообщение имеет тип "Файл"
		elseif chatHistory[currentChatID][i].type == "file" then
			if chatHistory[currentChatID][i].fromYou then
				y = drawFileCloud(xSender - 20, y, colors.yourCloudColor, colors.yourCloudTextColor, chatHistory[currentChatID][i].fromYou, chatHistory[currentChatID][i].message)
				buffer.image(xSender, y, avatars.personal)
			else
				y = drawFileCloud(xYou + 8, y, colors.senderCloudColor, colors.senderCloudTextColor, chatHistory[currentChatID][i].fromYou, chatHistory[currentChatID][i].message)
				buffer.image(xYou, y, avatars.contact)
			end
		else
			for i = chatZoneX, buffer.screen.width - 2 do
				buffer.set(i, y, colors.chatZone, colors.systemMessageColor, "─")
			end
			local x = math.floor(chatZoneX + (chatZoneWidth - 2) / 2 - unicode.len(chatHistory[currentChatID][i].message) / 2)
			buffer.text(x, y, colors.systemMessageColor, " " .. chatHistory[currentChatID][i].message .. " ")
		end

		y = y - 2
		if y <= yLeftBar then break end
	end

	-- Убираем ограничение отроисовки буфера
	buffer.resetDrawLimit()

	buffer.scrollBar(buffer.screen.width, yLeftBar, 1, chatZoneHeight, #chatHistory[currentChatID], currentChatMessage, colors.scrollBar, colors.scrollBarPipe)
end

local function drawMessageInputBar()
	local x, y = chatZoneX, yMessageInput
	buffer.square(x, y, chatZoneWidth, messageInputHeight, colors.messageInputBarColor, 0xFFFFFF, " ")
	y = y + 1
	buffer.square(x + 2, y, messageInputWidth, 3, colors.messageInputBarInputBackgroundColor, 0xFFFFFF, " ")
	buffer.text(x + 3, y + 1, colors.messsageInputBarTextColor, ecs.stringLimit("start", currentMessageText or "Введите сообщение", messageInputWidth - 2))

	obj.send = {buffer.button(chatZoneX + messageInputWidth + 4, y, sendButtonWidth, 3, colors.sendButtonColor, colors.sendButtonTextColor, "⇪")}
end

local function drawAll(force)
	drawTopBar()
	drawLeftBar()
	drawTopMenu()
	drawChat()
	drawMessageInputBar()
	buffer.draw(force)
end

local function scrollChat(direction)
	if direction == 1 then
		if currentChatMessage > 1 then
			currentChatMessage = currentChatMessage - 1
			drawChat()
			drawMessageInputBar()
			buffer.draw()
		end
	else
		if currentChatMessage < #chatHistory[currentChatID] then
			currentChatMessage = currentChatMessage + 1
			drawChat()
			drawMessageInputBar()
			buffer.draw()
		end
	end
end

local function addMessageToArray(ID, type, fromYou, message)
	table.insert(chatHistory[ID], {type = type, fromYou = fromYou, message = message})
	saveChatHistory()
end

local function sendMessage(type, message)
	modem.send(chatHistory[currentChatID].address, port, "HereIsMessageToYou", type, message)

	addMessageToArray(currentChatID, nil, true, currentMessageText)

	currentChatMessage = #chatHistory[currentChatID]
	currentMessageText = nil
end

local function checkAddressExists(address)
	for i = 1, #chatHistory do
		if chatHistory[i].address == address then
			return true
		end
	end
	return false
end

local function addNewContact(address, name, avatarData)
	if not checkAddressExists(address) then
		table.insert(chatHistory, 
		{
			address = address,
			name = name,
			{
				type = "system",
				message = "Здесь будет показана история чата"
			}
		})
		saveChatHistory()
		saveContactAvatar(#chatHistory, avatarData)
	end
end

local function askForAddToContacts(address)
	--Загружаем авку
	local file = io.open(personalAvatarPath, "r")
	local avatarData = file:read("*a")
	file:close()
	--Отсылаем свое имечко и аватарку
	modem.send(address, port, "AddMeToContactsPlease", chatHistory.myName, avatarData)
end

local function getNameAndIDOfAddress(address)
	for i = 1, #chatHistory do
		if chatHistory[i].address == address then
			return chatHistory[i].name, i
		end
	end
	return nil, nil
end

local function autoScroll()
	--Если мы никуда не скроллили и находимся в конце истории чата с этим юзером
	--То автоматически проскроллить на конец
	if currentChatMessage == (#chatHistory[currentChatID] - 1) then
		currentChatMessage = #chatHistory[currentChatID]
	end
end

local function receiveFile(remoteAddress, fileName)
	--Чекаем, есть ли он в контактах
	if checkAddressExists(remoteAddress) then
		--Создаем директорию под файлики, а то мало ли
		fs.makeDirectory(pathToSaveSendedFiles)
		--Получаем имя отправителя из контактов
		local senderName, senderID = getNameAndIDOfAddress(remoteAddress)
		--Открываем файл для записи
		local file = io.open(pathToSaveSendedFiles .. fileName, "w")
		--Запоминаем пиксели под окошком прогресса
		local oldPixels = ecs.progressWindow("auto", "auto", 40, 0, "Прием файла", true)
		--Начинаем ожидать беспроводных сообщений в течение 10 секунд
		while true do
			local fileReceiveEvent = { event.pull(10, "modem_message") }
			--Это сообщение несет в себе процентаж передачи и сами данные пакета
			if fileReceiveEvent[6] == "FILESEND" then
				--Рисуем окошко прогресса
				ecs.progressWindow("auto", "auto", 40, fileReceiveEvent[7], "Прием файла")
				file:write(fileReceiveEvent[8])
			--Если нам присылают сообщение о завершении передачи, то закрываем файл
			elseif fileReceiveEvent[6] == "FILESENDEND" then
				ecs.progressWindow("auto", "auto", 40, 100, "Прием файла")
				file:close()
				ecs.drawOldPixels(oldPixels)

				--Вставляем сообщение с файликом-иконочкой
				addMessageToArray(senderID, "file", nil, fileName)
				autoScroll()
				drawAll()

				--Выдаем окошечко о том, что файл успешно передан
				ecs.universalWindow("auto", "auto", 30, 0x262626, true,
					{"EmptyLine"},
					{"CenterText", ecs.colors.orange, "Прием данных завершен"},
					{"EmptyLine"},
					{"CenterText", 0xFFFFFF, "Файл от " .. senderName .. " сохранен как"},
					{"CenterText", 0xFFFFFF, "\"" .. pathToSaveSendedFiles .. fileName .. "\""},
					{"EmptyLine"},
					{"Button", {ecs.colors.orange, 0x262626, "OK"}}
				)

				break
			--Если не получали в течение указанного промежутка сообщений, то выдать сообщение об ошибке и удалить файл
			elseif not fileReceiveEvent[1] then
				file:close()
				ecs.drawOldPixels(oldPixels)
				fs.remove(pathToSaveSendedFiles .. fileName)
				ecs.error("Ошибка при передаче файла: клиент не отвечает")
				drawAll()
				break
			end
		end
	end
end

--Обработчик сообщений
local function dro4er(_, localAddress, remoteAddress, remotePort, distance, ...)
	local messages = { ... }
	
	if remotePort == port then
		if messages[1] == "AddMeToContactsPlease" then
			if modemConnection.remoteAddress and modemConnection.remoteAddress == remoteAddress then
				-- ecs.error("Сообщение о добавлении получил, адрес: " .. modemConnection.remoteAddress .. ", имя:" .. messages[2] .. ", авка: " .. type(messages[3]))
				--Добавляем пидорка к себе в контакты
				addNewContact(modemConnection.remoteAddress, messages[2], messages[3])
				--Просим того пидорка, чтобы он добавил нас к себе в контакты
				askForAddToContacts(modemConnection.remoteAddress)
				--Чтобы не было всяких соблазнов!
				modemConnection.availableUsers = {}
				modemConnection.remoteAddress = nil
				--Переключаемся на добавленный контакт
				switchToContact(#chatHistory)
				drawAll()
			end
		--Если какой-то чувак просит нас принять файл
		elseif messages[1] == "FAYLPRIMI" then
			receiveFile(remoteAddress, messages[2])
		elseif messages[1] == "HereIsMessageToYou" then
			for i = 1, #chatHistory do
				--Если в массиве истории чата найден юзер, отославший такое сообщение
				if chatHistory[i].address == remoteAddress then
					--То вставляем само сообщение в историю чата
					addMessageToArray(i, messages[2], nil, messages[3])
					--Если текущая открытая история чата является именно вот этой, с этим отправителем
					if currentChatID == i then
						autoScroll()
						--Обязательно отрисовываем измененную историю чата с этим отправителем
						drawChat()
						buffer.draw()
					--Увеличиваем количество непрочитанных сообщений от отправителя
					else
						chatHistory[i].unreadedMessages = chatHistory[i].unreadedMessages and chatHistory[i].unreadedMessages + 1 or 1
						drawLeftBar()
						buffer.draw()
					end

					--Бип!
					computer.beep(1700)

					--А это небольшой костыльчик, чтобы не сбивался цвет курсора Term API
					component.gpu.setBackground(colors.messageInputBarInputBackgroundColor)
					component.gpu.setForeground(colors.messsageInputBarTextColor)

					break
				end
			end
		end
	end
end

local function enableDro4er()
	event.listen("modem_message", dro4er)
end

local function disableDro4er()
	event.ignore("modem_message", dro4er)
end

local function deleteAvatar(ID)
	fs.remove(contactsAvatarsPath .. ID .. ".pic")
end

local function clearChatHistory()
	for i = 1, #chatHistory do
		deleteAvatar(i)
		chatHistory[i] = nil
	end
	saveChatHistory()
end

local function sendFile(path)
	local data = ecs.universalWindow("auto", "auto", 30, 0x262626, true,
		{"EmptyLine"},
		{"CenterText", ecs.colors.orange, "Отправить файл"},
		{"EmptyLine"},
		{"Input", 0xFFFFFF, ecs.colors.orange, "Путь"},
		{"EmptyLine"},
		{"Button", {ecs.colors.orange, 0x262626, "OK"}, {0x666666, 0xffffff, "Отмена"}}
	)

	if data[2] == "OK" then
		if fs.exists(data[1]) then
			--Отправляем сообщение о том, что мы собираемся отправить файл
			modem.send(chatHistory[currentChatID].address, port, "FAYLPRIMI", fs.name(data[1]))
			--Открываем файл и отправляем его по количеству пакетов
			local maxPacketSize = modem.maxPacketSize() - 32
			local file = io.open(data[1], "rb")
			local fileSize = fs.size(data[1])
			local percent = 0
			local sendedBytes = 0
			local dataToSend
		
			while true do
				dataToSend = file:read(maxPacketSize)
				if dataToSend then
					modem.send(chatHistory[currentChatID].address, port, "FILESEND", percent, dataToSend)
					sendedBytes = sendedBytes + maxPacketSize
					percent = math.floor(sendedBytes / fileSize * 100)
				else
					break
				end
			end
		
			file:close()
			--Репортуем об окончании передачи файла
			modem.send(chatHistory[currentChatID].address, port, "FILESENDEND")
			--Вставляем в чат инфу об обтправленном файле
			addMessageToArray(currentChatID, "file", true, fs.name(data[1]))
			autoScroll()
			drawAll()
		else
			ecs.error("Файл \"" .. data[1] .. "\" не существует.")
		end
	end
end

local function deleteContact(ID)
	table.remove(chatHistory, ID)
	deleteAvatar(ID)
	if #chatHistory > 0 then
		switchToContact(1)
	else
		currentChatID = 1
		currentChatMessage = 1
	end
	saveChatHistory()
end

-------------------------------------------------------------------------------------------------------------------------------

--Отключаем принудительное завершение программы
ecs.disableInterrupting()
--Загружаем историю чата и свою аватарку
loadChatHistory()
loadPersonalAvatar()
--Если история не пуста, то переключаемся на указанный контакт
if chatHistory[currentChatID] then
	switchToContact(currentChatID)
end
--Включаем прием данных по модему для подключения
modemConnection.startReceivingData()
--Отсылаем всем модемам сигнал о том, чтобы они удалили нас из своего списка
modemConnection.disconnect()
--Отправляем свои данные, чтобы нас заново внесли в список
modemConnection.sendPersonalData()
--Активируем прием сообщений чата
enableDro4er()
--Рисуем весь интерфейс
drawAll()

-------------------------------------------------------------------------------------------------------------------------------

while true do
	local e = { event.pull() }
	if e[1] == "touch" then
		-- Клик на поле ввода сообщения
		if #chatHistory > 0 and ecs.clickedAtArea(e[3], e[4], chatZoneX + 2, yMessageInput, chatZoneX + messageInputWidth + 2, yMessageInput + 3) then
			local text = ecs.inputText(chatZoneX + 3, yMessageInput + 2, messageInputWidth - 2, currentMessageText, colors.messageInputBarInputBackgroundColor, colors.messsageInputBarTextColor)
			if text ~= nil and text ~= "" then
				currentMessageText = text
				sendMessage(nil, currentMessageText)
				buffer.square(chatZoneX + 2, yMessageInput + 1, messageInputWidth, 3, colors.messageInputBarInputBackgroundColor, 0xFFFFFF, " ")
				buffer.draw()
				drawMessageInputBar()
				drawChat()
				buffer.draw()
			end
		-- Жмякаем на кнопочку "Отправить"
		elseif #chatHistory > 0 and ecs.clickedAtArea(e[3], e[4], obj.send[1], obj.send[2], obj.send[3], obj.send[4]) then
			buffer.button(obj.send[1], obj.send[2], sendButtonWidth, 3, colors.sendButtonTextColor, colors.sendButtonColor, "⇪")
			buffer.draw()
			os.sleep(0.2)
			drawMessageInputBar()
			buffer.draw()
			sendFile()
		-- Кнопа поиска
		elseif ecs.clickedAtArea(e[3], e[4], obj.search[1], obj.search[2], obj.search[3], obj.search[4]) then
			buffer.button(obj.search[1], obj.search[2], leftBarWidth, 3, colors.leftBarSearchButtonText, colors.leftBarSearchButton, "Поиск")
			buffer.draw()
			os.sleep(0.2)

			modemConnection.search()

			--Если после поиска мы подключились к какому-либо адресу
			if modemConnection.remoteAddress then
				--Просим адрес добавить нас в свой список контактов
				askForAddToContacts(modemConnection.remoteAddress)
			end

			drawAll(true)
		end

		--Клик на контакты
		for key in pairs(obj.Contacts) do
			if ecs.clickedAtArea(e[3], e[4], obj.Contacts[key][1], obj.Contacts[key][2], obj.Contacts[key][3], obj.Contacts[key][4]) then
				if e[5] == 0 then
					switchToContact(key)
					drawAll()
				else
					local action = context.menu(e[3], e[4], {"Переименовать"}, {"Удалить"})
					if action == "Переименовать" then
						local data = ecs.universalWindow("auto", "auto", 30, 0x262626, true,
							{"EmptyLine"},
							{"CenterText", ecs.colors.orange, "Переименовать контакт"},
							{"EmptyLine"},
							{"Input", 0xFFFFFF, ecs.colors.orange, chatHistory[key].name},
							{"EmptyLine"},
							{"Button", {ecs.colors.orange, 0x262626, "OK"}, {0x666666, 0xffffff, "Отмена"}}
						)

						if data[2] == "OK" then
							chatHistory[key].name = data[1] or chatHistory[key].name
							drawAll()
						end
					elseif action == "Удалить" then
						deleteContact(key)
						drawAll()
					end
				end

				break
			end
		end

		for key in pairs(obj.TopMenu) do
			if ecs.clickedAtArea(e[3], e[4], obj.TopMenu[key][1], obj.TopMenu[key][2], obj.TopMenu[key][3],obj.TopMenu[key][4]) then
				buffer.button(obj.TopMenu[key][1] - 1, obj.TopMenu[key][2], unicode.len(key) + 2, 1, ecs.colors.blue, 0xFFFFFF, key)
				buffer.draw()

				local action
				if key == "Чат" then
					action = context.menu(obj.TopMenu[key][1] - 1, obj.TopMenu[key][2] + 1, {"Изменить имя"}, {"Изменить аватар"}, {"Очистить историю"},"-", {"Выход"})
				elseif key == "О программе" then
					ecs.universalWindow("auto", "auto", 36, 0x262626, true, 
						{"EmptyLine"},
						{"CenterText", ecs.colors.orange, "Chat v1.0"}, 
						{"EmptyLine"},
						{"CenterText", 0xFFFFFF, "Автор:"},
						{"CenterText", 0xBBBBBB, "Тимофеев Игорь"},
						{"CenterText", 0xBBBBBB, "vk.com/id7799889"},
						{"EmptyLine"},
						{"CenterText", 0xFFFFFF, "Тестеры:"},
						{"CenterText", 0xBBBBBB, "Егор Палиев"},
						{"CenterText", 0xBBBBBB, "vk.com/mrherobrine"},
						{"CenterText", 0xBBBBBB, "Максим Хлебников"},
						{"CenterText", 0xBBBBBB, "vk.com/mskalash"},
						{"EmptyLine"},
						{"Button", {ecs.colors.orange, 0x262626, "OK"}}
					)
				end

				if action == "Выход" then
					disableDro4er()
					modemConnection.stopReceivingData()
					modemConnection.disconnect()
					ecs.enableInterrupting()
					modem.close(port)
					buffer.clear()
					ecs.prepareToExit()
					return
				elseif action == "Очистить историю" then
					clearChatHistory()
					drawAll()
				end

				drawTopMenu()
				buffer.draw()

				break
			end
		end

	elseif e[1] == "scroll" then
		if #chatHistory > 0 and ecs.clickedAtArea(e[3], e[4], chatZoneX, yLeftBar, chatZoneX + chatZoneWidth - 1, yLeftBar + chatZoneHeight - 1) then
			scrollChat(e[5])
		end
	end
end





