/* ScummVM - Graphic Adventure Engine
 *
 * ScummVM is the legal property of its developers, whose names
 * are too numerous to list here. Please refer to the COPYRIGHT
 * file distributed with this source distribution.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#include "titanic/pet_control/pet_inventory_glyphs.h"
#include "titanic/pet_control/pet_control.h"
#include "titanic/pet_control/pet_inventory.h"
#include "titanic/messages/pet_messages.h"
#include "titanic/titanic.h"

namespace Titanic {

const uint ITEM_MODES[40] = {
	0, 2, 11, 10, 12, 13, 9, 40, 7, 6,
	4, 5, 8, 15, 19, 24, 25, 26, 30, 20,
	21, 22, 23, 36, 39, 39, 31, 31, 32, 32,
	33, 34, 35, 38, 41, 42, 43, 44, 45, 37
};

void CPetInventoryGlyph::enter() {
	startRepeatedMovie();
}

void CPetInventoryGlyph::leave() {
	stopMovie();
}

void CPetInventoryGlyph::drawAt(CScreenManager *screenManager, const Point &pt, bool isHighlighted_) {
	if (!_active)
		return;

	if (_singular) {
		if (_singular->hasActiveMovie()) {
			if (isHighlighted_)
				_singular->draw(screenManager);
			else
				_singular->draw(screenManager, pt);
			return;
		}

		_singular = nullptr;
		if (_repeated && isHighlighted_) {
			_repeated->setPosition(pt);
			startRepeatedMovie();
		}
	}

	if (_repeated) {
		if (isHighlighted_)
			_repeated->draw(screenManager);
		else
			_repeated->draw(screenManager, pt);
	} else if (_singular) {
		_singular->draw(screenManager, pt, Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT));
	}
}


void CPetInventoryGlyph::unhighlightCurrent() {
	if (_singular) {
		_singular->setPosition(Point(0, 0));
		stopMovie();
	} else if (_repeated) {
		_repeated->setPosition(Point(0, 0));
		_repeated->loadFrame(0);
		stopMovie();
	}
}

void CPetInventoryGlyph::highlightCurrent(const Point &pt) {
	reposition(pt);
	if (_item) {
		CPETObjectSelectedMsg selectedMsg;
		selectedMsg.execute(_item);
	}
}

void CPetInventoryGlyph::glyphFocused(const Point &topLeft, bool flag) {
	if (_repeated && flag)
		_repeated->setPosition(topLeft);
}

bool CPetInventoryGlyph::dragGlyph(const Point &topLeft, CMouseDragStartMsg *msg) {
	if (!_item)
		return false;

	if (_repeated) {
		_active = false;
		stopMovie();
	}

	CPetControl *petControl = getPetControl();
	if (!petControl)
		return false;

	CGameObject *carryParcel = petControl->getHiddenObject("CarryParcel");
	CGameObject *item = _item;

	if (petControl->isSuccUBusActive() && carryParcel) {
		petControl->removeFromInventory(_item, carryParcel, false, true);
		petControl->removeFromInventory(_item, false, false);

		carryParcel->setPosition(Point(msg->_mousePos.x - carryParcel->_bounds.width() / 2,
			msg->_mousePos.y - carryParcel->_bounds.height() / 2));
		carryParcel->setPosition(Point(SCREEN_WIDTH, SCREEN_HEIGHT));
		item = carryParcel;
	} else {
		petControl->removeFromInventory(_item, false, true);

		_item->setPosition(Point(msg->_mousePos.x - _item->_bounds.width() / 2,
			msg->_mousePos.y - _item->_bounds.height() / 2));
		_item->setVisible(true);
	}

	msg->_handled = true;
	if (msg->execute(item)) {
		_item = nullptr;
		_repeated = nullptr;
		_active = false;
		petControl->setAreaChangeType(1);
		return true;
	} else {
		petControl->addToInventory(item);
		return false;
	}
}

void CPetInventoryGlyph::getTooltip(CTextControl *text) {
	if (text) {
		text->setText("");

		if (_active && _item) {
			int itemIndex = populateItem(_item, 0);
			if (itemIndex >= 14 && itemIndex <= 18) {
				// Variations of the chicken
				CPETObjectStateMsg stateMsg(0);
				stateMsg.execute(_item);

				CString temperature = g_vm->_strings[stateMsg._value ? A_HOT : A_COLD];
				text->setText(CString::format("%s %s", temperature.c_str(),
					g_vm->_itemDescriptions[itemIndex].c_str()
				));

			} else {
				text->setText(g_vm->_itemDescriptions[itemIndex]);
			}
		}
	}
}

bool CPetInventoryGlyph::doAction(CGlyphAction *action) {
	CInventoryGlyphAction *invAction = static_cast<CInventoryGlyphAction *>(action);
	CPetInventoryGlyphs *owner = dynamic_cast<CPetInventoryGlyphs *>(_owner);
	if (!invAction)
		return false;

	switch (invAction->getMode()) {
	case ACTION_REMOVED:
		if (invAction->_item == _item) {
			_item = nullptr;
			_repeated = nullptr;
			_active = false;
		}
		break;

	case ACTION_CHANGE:
		if (_item == invAction->_item && _owner) {
			int v = populateItem(_item, 0);
			_repeated = owner->getBackground(v);

			if (isHighlighted()) {
				Point glyphPos = _owner->getHighlightedGlyphPos();
				reposition(glyphPos);
				updateTooltip();
			}
		}
		break;

	default:
		break;
	}

	return true;
}

void CPetInventoryGlyph::setItem(CGameObject *item, bool isLoading) {
	_item = item;

	if (_owner && item) {
		int idx = populateItem(item, isLoading);
		_repeated = static_cast<CPetInventoryGlyphs *>(_owner)->getBackground(idx);
		_singular = static_cast<CPetInventory *>(getPetSection())->getTransformAnimation(idx);
	}
}

int CPetInventoryGlyph::populateItem(CGameObject *item, bool isLoading) {
	// Scan the master item names list
	CString itemName = item->getName();
	int itemIndex = -1;
	for (int idx = 0; idx < 40 && itemIndex == -1; ++idx) {
		if (itemName == g_vm->_itemIds[idx])
			itemIndex = idx;
	}
	if (itemIndex == -1)
		return -1;

	// Some objects can be in multiple different states. These are handled
	// below to give each the correct inventory glyph and description
	switch (ITEM_MODES[itemIndex]) {
	case 0:
		// Maitre d'Bot's left arm
		switch (getItemIndex(item, isLoading)) {
		case 0:
		case 1:
			return 0;
		case 2:
		case 3:
			return 1;
		default:
			return 0;
		}

	case 2:
		// Maitre d'Bot's right arm
		switch (getItemIndex(item, isLoading)) {
		case 0:
			return 2;
		default:
			return 3;
		}
		break;

	case 15:
		// Chicken
		switch (getItemIndex(item, isLoading)) {
		case 0:
		case 1:
			return 14;
		case 2:
			return 16;
		case 3:
			return 15;
		case 4:
			return 17;
		case 5:
			return 18;
		default:
			return 15;
		}
		break;

	case 26:
		// Beer glass
		switch (getItemIndex(item, isLoading)) {
		case 0:
			return 26;
		case 1:
			return 29;
		case 2:
			return 28;
		case 3:
			return 27;
		default:
			return 26;
		}
		break;

	default:
		break;
	}

	return ITEM_MODES[itemIndex];
}

int CPetInventoryGlyph::getItemIndex(CGameObject *item, bool isLoading) {
	int frameNum = item->getFrameNumber();
	int movieFrame = item->getMovieFrame();

	if (isLoading && frameNum != -1 && frameNum != movieFrame) {
		item->loadFrame(frameNum);
		movieFrame = frameNum;
	}

	return movieFrame;
}

void CPetInventoryGlyph::startRepeatedMovie() {
	if (_owner) {
		CPetInventory *section = dynamic_cast<CPetInventory *>(_owner->getOwner());
		if (section)
			section->playMovie(_repeated, true);
	}
}

void CPetInventoryGlyph::startSingularMovie() {
	if (_owner) {
		CPetInventory *section = dynamic_cast<CPetInventory *>(_owner->getOwner());
		if (section)
			section->playMovie(_singular, false);
	}
}

void CPetInventoryGlyph::stopMovie() {
	if (_owner) {
		CPetInventory *section = dynamic_cast<CPetInventory *>(_owner->getOwner());
		if (section)
			section->playMovie(nullptr);
	}
}

void CPetInventoryGlyph::reposition(const Point &pt) {
	if (_singular) {
		// Special transformation of item to piece of Titania
		_singular->setPosition(pt);
		startSingularMovie();
	} else if (_repeated) {
		// Standard repeating animation
		_repeated->setPosition(pt);
		startRepeatedMovie();
	}
}

/*------------------------------------------------------------------------*/

bool CPetInventoryGlyphs::doAction(CInventoryGlyphAction *action) {
	for (iterator i = begin(); i != end(); ++i) {
		(*i)->doAction(action);
	}

	return true;
}

CGameObject *CPetInventoryGlyphs::getBackground(int index) {
	return _owner ? _owner->getBackground(index) : nullptr;
}

} // End of namespace Titanic
