/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/***************************************************************************
 *            drumkitloader.cc
 *
 *  Thu Jan 17 20:54:14 CET 2013
 *  Copyright 2013 Bent Bisballe Nyeng
 *  deva@aasimon.org
 ****************************************************************************/

/*
 *  This file is part of DrumGizmo.
 *
 *  DrumGizmo is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU Lesser General Public License as published by
 *  the Free Software Foundation; either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  DrumGizmo 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 Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public License
 *  along with DrumGizmo; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA.
 */
#include "drumkitloader.h"

#include <iostream>

#include <hugin.hpp>

#include "drumkitparser.h"
#include "drumgizmo.h"

DrumKitLoader::DrumKitLoader(Settings& settings)
	: framesize(0)
	, settings(settings)
	, getter(settings)
{
	run();
	run_semaphore.wait(); // Wait for the thread to actually start.
}

DrumKitLoader::~DrumKitLoader()
{
	DEBUG(loader, "~DrumKitLoader() pre\n");

	if(running)
	{
		framesize_semaphore.post();
		stop();
	}

	DEBUG(loader, "~DrumKitLoader() post\n");
}

void DrumKitLoader::stop()
{
	{
		std::lock_guard<std::mutex> guard(mutex);
		load_queue.clear();
	}

	running = false;
	semaphore.post();
	wait_stop();
}

void DrumKitLoader::skip()
{
	std::lock_guard<std::mutex> guard(mutex);
	load_queue.clear();
}

void DrumKitLoader::setFrameSize(size_t framesize)
{
	std::lock_guard<std::mutex> guard(mutex);
	this->framesize = framesize;
	framesize_semaphore.post(); // Signal that the framesize has been set.
}

bool DrumKitLoader::isDone()
{
	std::lock_guard<std::mutex> guard(mutex);
	return load_queue.size() == 0;
}

void DrumKitLoader::loadKit(DrumKit *kit)
{
	std::lock_guard<std::mutex> guard(mutex);

	DEBUG(loader, "Create AudioFile queue from DrumKit\n");

	std::size_t total_num_audiofiles = 0;// For UI Progress Messages

	// Count total number of files that need loading:
	for(auto instr : kit->instruments)
	{
		total_num_audiofiles += instr->audiofiles.size();
	}

	settings.number_of_files.store(total_num_audiofiles);

	// Now actually queue them for loading:
	for(auto instr : kit->instruments)
	{
		std::vector<AudioFile*>::iterator af = instr->audiofiles.begin();
		while(af != instr->audiofiles.end())
		{
			AudioFile *audiofile = *af;
			load_queue.push_back(audiofile);
			af++;
		}
	}

	loaded = 0; // For UI Progress Messages

	DEBUG(loader, "Queued %d (size: %d) AudioFiles for loading.\n",
	      (int)total_num_audiofiles, (int)load_queue.size());

	semaphore.post(); // Start loader loop.
}

void DrumKitLoader::thread_main()
{
	running = true;

	run_semaphore.post(); // Signal that the thread has been started.

	framesize_semaphore.wait(); // Wait until the framesize has been set.

	while(running)
	{
		size_t size;
		{
			std::lock_guard<std::mutex> guard(mutex);
			size = load_queue.size();
		}

		// Only sleep if queue is empty.
		if(size == 0)
		{
			semaphore.wait(std::chrono::milliseconds(1000));
		}

		if(getter.drumkit_file.hasChanged())
		{
			//std::cout << "RELOAD DRUMKIT!" << std::endl;
		}

		if(getter.midimap_file.hasChanged())
		{
			//std::cout << "RELOAD MIDIMAP!" << std::endl;
		}

		std::string filename;
		{
			std::lock_guard<std::mutex> guard(mutex);

			if(load_queue.size() == 0)
			{
				continue;
			}

			AudioFile *audiofile = load_queue.front();
			load_queue.pop_front();
			filename = audiofile->filename;
			int preload_size = framesize * CHUNK_MULTIPLIER + framesize;
			if(preload_size < 1024)
			{
				preload_size = 1024;
			}

			// Note: Remove this line to enable diskstreaming
			preload_size = ALL_SAMPLES;

			audiofile->load(preload_size);
		}

		++loaded;

		settings.number_of_files_loaded.store(loaded);

		if(settings.number_of_files.load() == loaded)
		{
			settings.drumkit_load_status.store(LoadStatus::Done);
		}
	}

	DEBUG(loader, "Loader thread finished.");
}