#include <stdio.h>
#include <windows.h>
#include "identifiers.h"
#include "qbtypes.h"
#include "songlistwrite.h"
#include "qbkey32.h"
#include "makeqb.h"
#include "write_endian.h"

 /* This program is free software. It comes without any warranty, to
 * the extent permitted by applicable law. You can redistribute it
 * and/or modify it under the terms of the Do What The Fuck You Want
 * To Public License, Version 2, as published by Sam Hocevar. See
 * http://sam.zoy.org/wtfpl/COPYING for more details. */

FILE *OpenSongListWrite(HWND hDlg, char *songlistName)
{
	FILE *qbFile;

	qbFile = fopen(songlistName, "wb+");

	if (qbFile == NULL)
	{
		MessageBox(hDlg, "Can't open the QB file!", NULL, MB_OK | MB_ICONERROR);
		return NULL;
	}

	setvbuf(qbFile, NULL, _IONBF, 0);

	return qbFile;
}

int WriteOutFile(HWND hDlg, FILE *qbFile, QBReturnInfo *qbInfo)
{
	QBHeader header;
	unsigned int fileId = makeQBKey("scripts\\guitar\\songlist.qb");
	int structPtr, songEntryPtr, i; // To link the structures...
	QBSongInfo *currSong;

	/* Make header */
	header.magic = 0;
	header.fileSize = 0;
	char weirdThing[20] = { 0x1C, 0x08, 0x02, 0x04, 0x10, 0x04, 0x08, 0x0C, 0x0C, 0x08, 0x02, 0x04, 0x14, 0x02, 0x04, 0x0C, 0x10, 0x10, 0x0C, 0x00 };
	
	fwriteBe(&header, 4, 2, qbFile);
	fwrite(&weirdThing, 1, 20, qbFile);

	/* Put gh3_songlist (some identifiers) */
	makeSimpleDataSection(qbFile, SECTION_ARRAY, fileId, makeQBKey("gh3_songlist"));
	makeQBKeyArray(qbFile, qbInfo->numSongIdentifiers, qbInfo->songIdentifiers);

	/* Put download_songlist (null section = vector 0,0) */
	makeSimpleDataSection(qbFile, SECTION_ARRAY, fileId, makeQBKey("download_songlist"));
	makeVector(qbFile, 0.0, 0.0);

	/* Put download_songlist_props (null struct) */
	makeSimpleDataSection(qbFile, SECTION_STRUCT_BI, fileId, makeQBKey("download_songlist_props"));
	structPtr = makeStructDeclaration(qbFile);
	closeStruct(qbFile, structPtr);

	/* Put gh3_songlist_props (struct with 2 members) */
	makeSimpleDataSection(qbFile, SECTION_STRUCT_BI, fileId, makeQBKey("gh3_songlist_props"));
	structPtr = makeStructDeclaration(qbFile);
	structPtr = makeStructSimple(qbFile, STRUCT_CRC, 0x00000000, makeQBKey("download_songlist_props"), structPtr);
	structPtr = makeStructSimple(qbFile, STRUCT_CRC, 0x00000000, makeQBKey("permanent_songlist_props"), structPtr);
	closeStruct(qbFile, structPtr);

	/* Put artist_text_by */
	makeStringSection(qbFile, fileId, makeQBKey("artist_text_by"), qbInfo->textBy);

	/* Put artist_text_as_made_famous_by */
	makeStringSection(qbFile, fileId, makeQBKey("artist_text_as_made_famous_by"), qbInfo->textAsMadeFamousBy);

	/* Put permanent_songlist_props (aka. the setlist) */
	makeSimpleDataSection(qbFile, SECTION_STRUCT_BI, fileId, makeQBKey("permanent_songlist_props"));

	songEntryPtr = makeStructDeclaration(qbFile);

	// Make substructs...
	for (i = 0; i < qbInfo->numSongs; i++)
	{
		currSong = qbInfo->songs[i]; // Quick pointer

		if (!currSong->internalFlags & IS_SONGNAMECHECKSUM)
		{
			MessageBox(hDlg, "(FATAL) ERROR: One of the songs doesn't have his checksum!", NULL, MB_OK);
			return -1;
		}

		songEntryPtr = makeStructPointer(qbFile, STRUCT_SUBITEM, currSong->songNameChecksum, songEntryPtr);

		structPtr = makeStructDeclaration(qbFile);

		if (currSong->internalFlags & IS_SONGNAMECHECKSUM) // Song name checksum
			structPtr = makeStructSimple(qbFile, STRUCT_CRC_BI, makeQBKey("checksum"), currSong->songNameChecksum, structPtr);

		if (currSong->internalFlags & IS_SONGINTERNALNAME) // Song internal name
			structPtr = makeStructString(qbFile, makeQBKey("name"), currSong->songInternalName, structPtr);

		if (currSong->internalFlags & IS_SONGNAME) // Song name/title
			structPtr = makeStructString(qbFile, makeQBKey("title"), currSong->songName, structPtr);

		if (currSong->internalFlags & IS_SONGAUTHOR) // Song author
			structPtr = makeStructString(qbFile, makeQBKey("artist"), currSong->songAuthor, structPtr);

		if (currSong->internalFlags & IS_SONGYEAR) // Song year
			structPtr = makeStructString(qbFile, makeQBKey("year"), currSong->songYear, structPtr);

		if (currSong->internalFlags & IS_ARTISTTEXTKEY) // Artist text (CRC or string)
			structPtr = makeStructSimple(qbFile, STRUCT_CRC, makeQBKey("artist_text"), currSong->artistTextKey, structPtr);
		else if (currSong->internalFlags & IS_ARTISTTEXT)
			structPtr = makeStructString(qbFile, makeQBKey("artist_text"), currSong->artistText, structPtr);

		if (currSong->internalFlags & IS_ISORIGINALARTIST) // Cover
			structPtr = makeStructSimple(qbFile, STRUCT_INTEGER, makeQBKey("original_artist"), currSong->isOriginalArtist, structPtr);

		if (currSong->internalFlags & IS_STARTUPSCRIPT) // Startup script
			structPtr = makeStructSimple(qbFile, STRUCT_CRC_BI, makeQBKey("startup_script"), currSong->startupScript, structPtr);

		if (currSong->internalFlags & IS_GAMEVERSION) // Version ???
			structPtr = makeStructSimple(qbFile, STRUCT_CRC_BI, makeQBKey("version"), currSong->gameVersion, structPtr);

		if (currSong->internalFlags & IS_USELEADERBOARD) // Leaderboard
			structPtr = makeStructSimple(qbFile, STRUCT_INTEGER, makeQBKey("leaderboard"), currSong->useLeaderboard, structPtr);

		if (currSong->internalFlags & IS_GEMOFFSET) // Gem offset ???
			structPtr = makeStructSimple(qbFile, STRUCT_INTEGER, makeQBKey("gem_offset"), currSong->gemOffset, structPtr);

		if (currSong->internalFlags & IS_FRETBAROFFSET) // Fretbar offset ???
			structPtr = makeStructSimple(qbFile, STRUCT_INTEGER, makeQBKey("fretbar_offset"), currSong->fretbarOffset, structPtr);

		if (currSong->internalFlags & IS_INPUTOFFSET) // Input offset ???
			structPtr = makeStructSimple(qbFile, STRUCT_INTEGER, makeQBKey("input_offset"), currSong->inputOffset, structPtr);

		if (currSong->internalFlags & IS_BOSSID) // Boss ID
			structPtr = makeStructSimple(qbFile, STRUCT_CRC_BI, makeQBKey("boss"), currSong->bossId, structPtr);

		if (currSong->internalFlags & IS_FORCEDBASSIST) // Bassist (forced)
			structPtr = makeStructString(qbFile, makeQBKey("bassist"), currSong->forcedBassist, structPtr);

		if (currSong->internalFlags & IS_SINGERTYPE) // Singer
			structPtr = makeStructSimple(qbFile, STRUCT_CRC_BI, makeQBKey("singer"), currSong->singerType, structPtr);

		if (currSong->internalFlags & IS_USEKEYBOARD) // Kboard
			structPtr = makeStructSimple(qbFile, STRUCT_CRC_BI, makeQBKey("keyboard"), currSong->useKeyboard, structPtr);

		if (currSong->internalFlags & IS_EXITSCRIPT)
			structPtr = makeStructSimple(qbFile, STRUCT_CRC_BI, makeQBKey("exit_script"), currSong->exitScript, structPtr);

		if (currSong->internalFlags & IS_NULLPARAM) // "Null" (extra) parameter
			structPtr = makeStructSimple(qbFile, STRUCT_CRC_BI, 0, currSong->nullParam, structPtr);

		if (currSong->internalFlags & IS_COUNTOFF) // Countoff
			structPtr = makeStructString(qbFile, makeQBKey("countoff"), currSong->countOff, structPtr);

		if (currSong->internalFlags & IS_USERHYTHMTRACK) // Rhythm track
			structPtr = makeStructSimple(qbFile, STRUCT_INTEGER, makeQBKey("rhythm_track"), currSong->useRhythmTrack, structPtr);

		if (currSong->internalFlags & IS_BANDVOLUME) // Band volume
			structPtr = makeStructFloat(qbFile, makeQBKey("band_playback_volume"), currSong->bandVolume, structPtr);

		if (currSong->internalFlags & IS_GUITARVOLUME) // Guitar volume
			structPtr = makeStructFloat(qbFile, makeQBKey("guitar_playback_volume"), currSong->bandVolume, structPtr);

		if (currSong->internalFlags & IS_HAMMERONMEASURESCALE)
			structPtr = makeStructFloat(qbFile, makeQBKey("hammer_on_measure_scale"), currSong->hammerOnMeasureScale, structPtr);

		closeStruct(qbFile, structPtr);
	}

	closeStruct(qbFile, songEntryPtr);

	/* Finally! Now for the scripts */
	for (i = 0; i < qbInfo->numScripts; i++)
		makeScriptSection(qbFile, fileId, qbInfo->scripts[i]);

	/* EOF!!111!!21! */
	finishQB(qbFile);

	return 0;
}
