/* 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 2
 * 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, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 *
 */

#include "common/archive.h"

#include "audio/audiostream.h"
#include "audio/decoders/wave.h"

#include "prince/prince.h"
#include "prince/hero.h"
#include "prince/script.h"

namespace Prince {

void PrinceEngine::playSample(uint16 sampleId, uint16 loopType) {
	if (_audioStream[sampleId]) {
		if (_mixer->isSoundIDActive(sampleId)) {
			return;
		}
		_audioStream[sampleId]->rewind();
		if (sampleId < 28) {
			_mixer->playStream(Audio::Mixer::kSFXSoundType, &_soundHandle[sampleId], _audioStream[sampleId], sampleId, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO);
		} else {
			_mixer->playStream(Audio::Mixer::kSpeechSoundType, &_soundHandle[sampleId], _audioStream[sampleId], sampleId, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO);
		}
	}
}

void PrinceEngine::stopSample(uint16 sampleId) {
	_mixer->stopID(sampleId);
}

void PrinceEngine::stopAllSamples() {
	_mixer->stopAll();
}

void PrinceEngine::freeSample(uint16 sampleId) {
	stopSample(sampleId);
	if (_audioStream[sampleId] != nullptr) {
		delete _audioStream[sampleId];
		_audioStream[sampleId] = nullptr;
	}
}

void PrinceEngine::freeAllSamples() {
	for (int sampleId = 0; sampleId < kMaxSamples; sampleId++) {
		freeSample(sampleId);
	}
}

bool PrinceEngine::loadSample(uint32 sampleSlot, const Common::String &streamName) {
	// FIXME: This is just a workaround streamName is a path
	// SOUND\\SCIERKA1.WAV for now only last path component is used
	Common::String normalizedPath = lastPathComponent(streamName, '\\');

	// WALKAROUND: Wrong name in script, not existing sound in data files
	if (!normalizedPath.compareTo("9997BEKA.WAV")) {
		return 0;
	}

	debugEngine("loadSample slot %d, name %s", sampleSlot, normalizedPath.c_str());

	freeSample(sampleSlot);
	Common::SeekableReadStream *sampleStream = SearchMan.createReadStreamForMember(normalizedPath);
	if (sampleStream == nullptr) {
		delete sampleStream;
		error("Can't load sample %s to slot %d", normalizedPath.c_str(), sampleSlot);
	}
	_audioStream[sampleSlot] = Audio::makeWAVStream(sampleStream, DisposeAfterUse::NO);
	delete sampleStream;
	return true;
}

bool PrinceEngine::loadVoice(uint32 slot, uint32 sampleSlot, const Common::String &streamName) {
	if (getFeatures() & GF_NOVOICES)
		return false;

	debugEngine("Loading wav %s slot %d", streamName.c_str(), slot);

	if (slot >= kMaxTexts) {
		error("Text slot bigger than MAXTEXTS %d", kMaxTexts - 1);
		return false;
	}

	freeSample(sampleSlot);
	Common::SeekableReadStream *sampleStream = SearchMan.createReadStreamForMember(streamName);
	if (sampleStream == nullptr) {
		warning("loadVoice: Can't open %s", streamName.c_str());
		return false;
	}

	uint32 id = sampleStream->readUint32LE();
	if (id != MKTAG('F', 'F', 'I', 'R')) {
		error("It's not RIFF file %s", streamName.c_str());
		return false;
	}

	sampleStream->skip(0x20);
	id = sampleStream->readUint32LE();
	if (id != MKTAG('a', 't', 'a', 'd')) {
		error("No data section in %s id %04x", streamName.c_str(), id);
		return false;
	}

	id = sampleStream->readUint32LE();
	debugEngine("SetVoice slot %d time %04x", slot, id);
	id <<= 3;
	id /= 22050;
	id += 2;

	_textSlots[slot]._time = id;
	if (!slot) {
		_mainHero->_talkTime = id;
	} else if (slot == 1) {
		_secondHero->_talkTime = id;
	}

	debugEngine("SetVoice slot %d time %04x", slot, id);
	sampleStream->seek(SEEK_SET);
	_audioStream[sampleSlot] = Audio::makeWAVStream(sampleStream, DisposeAfterUse::NO);
	delete sampleStream;
	return true;
}

void PrinceEngine::setVoice(uint16 slot, uint32 sampleSlot, uint16 flag) {
	Common::String sampleName;
	uint32 currentString = _interpreter->getCurrentString();

	if (currentString >= 80000) {
		uint32 nr = currentString - 80000;
		sampleName = Common::String::format("%02d0%02d-%02d.WAV", nr / 100, nr % 100, flag);
	} else if (currentString >= 70000) {
		sampleName = Common::String::format("inv%02d-01.WAV", currentString - 70000);
	} else if (currentString >= 60000) {
		sampleName = Common::String::format("M%04d-%02d.WAV", currentString - 60000, flag);
	} else if (currentString >= 2000) {
		return;
	} else if (flag >= 100) {
		sampleName = Common::String::format("%03d-%03d.WAV", currentString, flag);
	} else {
		sampleName = Common::String::format("%03d-%02d.WAV", currentString, flag);
	}

	loadVoice(slot, sampleSlot, sampleName);
}

} // End of namespace Prince