

#include "stdafx.h"
#include <Windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "AVRCommandDecoder.h"

// This has to be "big enough" for any of the text conversions
//
constexpr auto TEXTBUFLEN = 50;

const char *BusyToText(uint8_t val) {
	static char buf[16];
	if (val == 0) {
		strcpy_s(buf, sizeof(buf), "OK");
	} else if (val == 1) {
		strcpy_s(buf, sizeof(buf), "BUSY");
	} else {
		sprintf_s(buf, sizeof(buf), "0x%02X ?", (unsigned char)val);
	}
	return buf;
}

const char *WarnToText(uint8_t val) {
	static char buf[16];
	if (val == 0) {
		strcpy_s(buf, sizeof(buf), "OK");
	} else if (val == 1) {
		strcpy_s(buf, sizeof(buf), "BUSY");
	} else {
		sprintf_s(buf, sizeof(buf), "0x%02X ?", (unsigned char)val);
	}
	return buf;
}

const char *PlaybackToText(uint8_t val) {
	static char buf[60];
	const char *playbackList[] = {
		/* 0 */ "6Ch Input",
		/* 1 */ "Analog",
		/* 2 */ "PCM",
		/* 3 */ "DD (except 2/0)",
		/* 4 */ "DD (2/0)",
		/* 5 */ "DD Karaoke",
		/* 6 */ "DD EX",
		/* 7 */ "DTS",
		/* 8 */ "DTS ES",
		/* 9 */ "Other Digital",
		/* A */ "DTS Analog Mute",
		/* B */ "DTS Discrete",
		/* C */ "Other than AAC 2/0",
		/* D */ "AAC 2/0",
	};
	if (val < sizeof(playbackList) / sizeof(playbackList[0]))
		strcpy_s(buf, sizeof(buf), playbackList[val]);
	else
		sprintf_s(buf, sizeof(buf), "0x%04X ?", val);
	return buf;
}

const char *FsToText(uint8_t val) {
	static char buf[60];
	const char *fsList[] = {
		/* 0 */ "Analog",
		/* 1 */ "32 kHz",
		/* 2 */ "44.1 kHz",
		/* 3 */ "48 kHz",
		/* 4 */ "64 kHz",
		/* 5 */ "88.2 kHz",
		/* 6 */ "96 kHz",
		/* 7 */ "unknown",
		/* 8 */ "128.0 kHz unk",
		/* 9 */ "176.4 kHz unk",
		/* A */ "192.0 kHz unk",
	};
	if (val < sizeof(fsList) / sizeof(fsList[0]))
		strcpy_s(buf, sizeof(buf), fsList[val]);
	else
		sprintf_s(buf, sizeof(buf), "0x%04X ?", val);
	return buf;
}



const char *OffOnText(uint8_t val) {
	static char buf[16];
	if (val == 0) {
		strcpy_s(buf, sizeof(buf), "Off");
	} else if (val == 1) {
		strcpy_s(buf, sizeof(buf), "On");
	} else {
		sprintf_s(buf, sizeof(buf), "0x%04X ?", val);
	}
	return buf;
}

const char *YesNoneText(uint8_t val) {
	static const char *buf[] = {
		"Yes", "None", "Unk"
	};
	if (val >= sizeof(buf) / sizeof(buf[0]))
		val = sizeof(buf) / sizeof(buf[0]) - 1;
	return buf[val];
}

const char *PRSBText(uint8_t val) {
	static const char *buf[] = {
		"PR", "SB", "Unk"
	};
	if (val >= sizeof(buf) / sizeof(buf[0]))
		val = sizeof(buf) / sizeof(buf[0]) - 1;
	return buf[val];
}

const char *OffMatrixDiscreteText(uint8_t val) {
	static const char *buf[] = {
		"Off", "Matrix On", "Discrete On", "Unk"
	};
	if (val >= sizeof(buf) / sizeof(buf[0]))
		val = sizeof(buf) / sizeof(buf[0]) - 1;
	return buf[val];
}

const char *OffMatrixDiscreteAutoText(uint8_t val) {
	static const char *buf[] = {
		"Off", "Matrix On", "Discrete On", "Auto", "Unk"
	};
	if (val >= sizeof(buf) / sizeof(buf[0]))
		val = sizeof(buf) / sizeof(buf[0]) - 1;
	return buf[val];
}

const char *ReleaseWaitText(uint8_t val) {
	static const char *buf[] = {
		"Release", "Wait", "Unk"
	};
	if (val >= sizeof(buf) / sizeof(buf[0]))
		val = sizeof(buf) / sizeof(buf[0]) - 1;
	return buf[val];
}

const char *NotTunedTunedText(uint8_t val) {
	static const char *buf[] = {
		"Not Tuned", "Tuned", "Unk"
	};
	if (val >= sizeof(buf) / sizeof(buf[0]))
		val = sizeof(buf) / sizeof(buf[0]) - 1;
	return buf[val];
}

const char *InputModeText(uint8_t val) {
	static const char *buf[] = {
		"Auto", "unk", "DTS", "unk", "Analog", "Analog Only", "AAC", "Unk"
	};
	if (val >= sizeof(buf) / sizeof(buf[0]))
		val = sizeof(buf) / sizeof(buf[0]) - 1;
	return buf[val];
}

const char *SwfrMainBothText(uint8_t val) {
	static const char *buf[] = {
		"Subwoofer", "Main", "Both", "Unk"
	};
	if (val >= sizeof(buf) / sizeof(buf[0]))
		val = sizeof(buf) / sizeof(buf[0]) - 1;
	return buf[val];
}

const char *LrFrNoneText(uint8_t val) {
	static const char *buf[] = {
		"L-R", "F-R", "None", "Unk"
	};
	if (val >= sizeof(buf) / sizeof(buf[0]))
		val = sizeof(buf) / sizeof(buf[0]) - 1;
	return buf[val];
}

const char *CenterMainText(uint8_t val) {
	static const char *buf[] = {
		"Center", "Main", "Unk"
	};
	if (val >= sizeof(buf) / sizeof(buf[0]))
		val = sizeof(buf) / sizeof(buf[0]) - 1;
	return buf[val];
}

const char *SwfrMainText(uint8_t val) {
	static const char *buf[] = {
		"Subwoofer", "Main", "Unk"
	};
	if (val >= sizeof(buf) / sizeof(buf[0]))
		val = sizeof(buf) / sizeof(buf[0]) - 1;
	return buf[val];
}

const char *SurrMainText(uint8_t val) {
	static const char *buf[] = {
		"Surround", "Main", "Unk"
	};
	if (val >= sizeof(buf) / sizeof(buf[0]))
		val = sizeof(buf) / sizeof(buf[0]) - 1;
	return buf[val];
}

const char *SixEightText(uint8_t val) {
	static const char *buf[] = {
		"6 Ch", "8 Ch", "Unk"
	};
	if (val >= sizeof(buf) / sizeof(buf[0]))
		val = sizeof(buf) / sizeof(buf[0]) - 1;
	return buf[val];
}

const char *CrossOverText(uint8_t val) {
	static char buf[16];
	static const uint8_t Hz[] = {
		40, 60, 80, 90, 100, 110, 120, 160, 200, 0
	};
	if (val >= sizeof(buf) / sizeof(buf[0]))
		val = sizeof(buf) / sizeof(buf[0]) - 1;
	sprintf_s(buf, sizeof(buf), "%d Hz", Hz[val]);
	return buf;
}

const char *OffDolbyDspText(uint8_t val) {
	static const char *buf[] = {
		"Off", "Dolby", "DSP"
	};
	if (val >= sizeof(buf) / sizeof(buf[0]))
		val = sizeof(buf) / sizeof(buf[0]) - 1;
	return buf[val];
}

const char *OffOn2OnMultiText(uint8_t val) {
	static const char *buf[] = {
		"Off", "On (2 Ch)", "On (Multi)"
	};
	if (val >= sizeof(buf) / sizeof(buf[0]))
		val = sizeof(buf) / sizeof(buf[0]) - 1;
	return buf[val];
}


const char *Norm10dbDownText(uint8_t val) {
	static const char *buf[] = {
		"Normal", "-10 db", "Unk"
	};
	if (val >= sizeof(buf) / sizeof(buf[0]))
		val = sizeof(buf) / sizeof(buf[0]) - 1;
	return buf[val];
}

const char *Zone1Zone2Text(uint8_t val) {
	static const char *buf[] = {
		"Zone 1", "Zone 2", "Unk"
	};
	if (val >= sizeof(buf) / sizeof(buf[0]))
		val = sizeof(buf) / sizeof(buf[0]) - 1;
	return buf[val];
}


const char *FMAMText(uint8_t val) {
	static const char *buf[] = {
		"FM", "AM", "Unk"
	};
	if (val >= sizeof(buf) / sizeof(buf[0]))
		val = sizeof(buf) / sizeof(buf[0]) - 1;
	return buf[val];
}

const char *AutoLastText(uint8_t val) {
	static const char *buf[] = {
		"Auto", "Last", "Unk"
	};
	if (val >= sizeof(buf) / sizeof(buf[0]))
		val = sizeof(buf) / sizeof(buf[0]) - 1;
	return buf[val];
}

const char *OSDFullShortOffText(uint8_t val) {
	static const char *buf[] = {
		"Full", "Short", "Off", "Unk"
	};
	if (val >= sizeof(buf) / sizeof(buf[0]))
		val = sizeof(buf) / sizeof(buf[0]) - 1;
	return buf[val];
}

const char *SleepTimerText(uint8_t val) {
	static const char *buf[] = {
		"120 min", "90 min", "60 min", "30 min", "Off", "Unk"
	};
	if (val >= sizeof(buf) / sizeof(buf[0]))
		val = sizeof(buf) / sizeof(buf[0]) - 1;
	return buf[val];
}

const char *PresetLabelText(uint8_t val) {
	static const char *buf[] = {
		"A", "B", "C", "D", "E", "F", "Unk"
	};
	if (val >= sizeof(buf) / sizeof(buf[0]))
		val = sizeof(buf) / sizeof(buf[0]) - 1;
	return buf[val];
}

const char *PresetNumberText(uint8_t val) {
	static const char *buf[] = {
		"1", "2", "3", "4", "5", "6", "7", "8", "Unk"
	};
	if (val >= sizeof(buf) / sizeof(buf[0]))
		val = sizeof(buf) / sizeof(buf[0]) - 1;
	return buf[val];
}

const char *MainSubAllText(uint8_t val) {
	static const char *buf[] = {
		"Main", "Sub", "All", "Unk"
	};
	if (val >= sizeof(buf) / sizeof(buf[0]))
		val = sizeof(buf) / sizeof(buf[0]) - 1;
	return buf[val];
}

const char *WhichZoneText(uint8_t val) {
	static const char *buf[] = {
		"All", "Zone 1", "Zone 2", "Zone 3", "Unk"
	};
	if (val >= sizeof(buf) / sizeof(buf[0]))
		val = sizeof(buf) / sizeof(buf[0]) - 1;
	return buf[val];
}

const char *OffAutoText(uint8_t val) {
	static const char *buf[] = {
		"Off", "Auto", "Unk"
	};
	if (val >= sizeof(buf) / sizeof(buf[0]))
		val = sizeof(buf) / sizeof(buf[0]) - 1;
	return buf[val];
}

const char *MaxStdMinText(uint8_t val) {
	static const char *buf[] = {
		"Max", "Std", "Min", "Unk"
	};
	if (val >= sizeof(buf) / sizeof(buf[0]))
		val = sizeof(buf) / sizeof(buf[0]) - 1;
	return buf[val];
}

const char *VarFixText(uint8_t val) {
	static const char *buf[] = {
		"Var", "Fix", "Unk"
	};
	if (val >= sizeof(buf) / sizeof(buf[0]))
		val = sizeof(buf) / sizeof(buf[0]) - 1;
	return buf[val];
}

const char *LSNText(uint8_t val) {
	static const char *buf[] = {
		"Large", "Small", "None", "Unk"
	};
	if (val >= sizeof(buf) / sizeof(buf[0]))
		val = sizeof(buf) / sizeof(buf[0]) - 1;
	return buf[val];
}

const char *LLSSNText(uint8_t val) {
	static const char *buf[] = {
		"Large x 2", "Large x1", "Small x 2", "Small x 1", "None", "Unk"
	};
	if (val >= sizeof(buf) / sizeof(buf[0]))
		val = sizeof(buf) / sizeof(buf[0]) - 1;
	return buf[val];
}

const char *Mode1Mode2Text(uint8_t val) {
	static const char *buf[] = {
		"Mode 1", "Mode 2", "Unk"
	};
	if (val >= sizeof(buf) / sizeof(buf[0]))
		val = sizeof(buf) / sizeof(buf[0]) - 1;
	return buf[val];
}

const char *ZonePower(uint8_t val) {
	static char buf[60];
	const char *powerList[8] = {
		/* 0 */ "All Off",
		/* 1 */ "All On",
		/* 2 */ "Zone 1 On  | 2,3 Off",
		/* 3 */ "Zone 1 Off | 2,3 On",
		/* 4 */ "Zone 1,2 On  | 3 Off",
		/* 5 */ "Zone 1 On  | 2,3 Off",
		/* 6 */ "Zone 1 Off | 2,3 On",
		/* 7 */ "Zone 1,2 Off | 3 On",
	};
	if (val < 8)
		strcpy_s(buf, sizeof(buf), powerList[val]);
	else
		sprintf_s(buf, sizeof(buf), "0x%04X ?", val);
	return buf;
}

const char *InputText(uint8_t val) {
	const char *buf[] = {
		"0:Phono", "1:CD", "2:Tuner", "3:CD-R", "4:MD-Tape", "5:DVD", "6:D-TV", "7:Cable", "8:unk",
		"9:VCR1", "A:VCR2", "B:unk", "C:V-Aux", "D:unk", "E:unk", "F:unk",
		"6 Ch 0:Phono", "6 Ch 1:CD", "6 Ch 2:Tuner", "6 Ch 3:CD-R", "6 Ch 4:MD-Tape", "6 Ch 5:DVD", "6 Ch 6:D-TV", "6 Ch 7:Cable", "6 Ch 8:unk",
		"6 Ch 9:VCR1", "6 Ch A:VCR2", "6 Ch B:unk", "6 Ch C:V-Aux", "6 Ch D:unk", "6 Ch E:unk", "6 Ch F:unk",
		"unknown"
	};
	if (val >= sizeof(buf) / sizeof(buf[0]))
		val = sizeof(buf) / sizeof(buf[0]) - 1;
	return buf[val];
}

const char *ProgramName(uint8_t val) {
	static char returnBuf[TEXTBUFLEN] = "";

	returnBuf[0] = '\0';
	if (val & 0x80) {
		strcpy_s(returnBuf, TEXTBUFLEN, "St.");
	}
	val &= 0x7F;		// Not accommodating the other variants yet
	const char *nameList[] = {
		"Hall A",	// (HALL1)
		"Hall B",
		"Hall C",
		"Hall_C2",
		"Hall E",
		"Live Concert",	//  (HALL2)
		"Tokyo",
		"Church",		// Freiburg (CHURCH)
		"Royaumont",
		"Village Gate",
		"Vanguard",	// Village Vanguard
		"Jazz",		// The Bottom Line (JAZZ)
		"Rock",		// The Roxy Theater (ROCK)
		"Warehouse",	// Warehouse Loft
		"Arena",
		"Disco",
		"Party",
		"Game",
		"7 Ch Stereo",
		"Music Video",	// Pop/Rock (Music Video)
		"DJ",
		"Opera",
		"Pavillion",
		"Mono Movie",
		"Sports",		// Variety Sports
		"Spectacre",
		"Sci-Fi",
		"Adventure",
		"General",
		"Normal",
		"Enhanced",
		"PLII Movie",
		"PLII Music",
		"Neo: 6 Movie",
		"Neo: 6 Music",
		"Stereo A 2Ch",
		"Direct B 2Ch"
		"THX A Cinema",
		"THX B Music",
	};
	if (val < sizeof(nameList)) {
		strcat_s(returnBuf, TEXTBUFLEN, nameList[val]);
	} else {
		strcpy_s(returnBuf, TEXTBUFLEN, "huh?");
	}
	return returnBuf;
}



// VolumeDB
// 
// Convert the communication units of volume into db
// 
// Piecewise
//	 for values 0 to 199
//		db = 0.5634 x - 112.11
//	 for values 200 to 255
//		db = 0.5 x - 99.5
// Single Linear according to the manual
//		db = 0.5574 x - 111.45
// Single Linear according to the on-screen display of Volume
//		db = 0.5 x - 99.5
//
const char *VolumeDB(uint8_t val) {
	static char buf[16];
	float m, b;

	//if (val < 200) {
	//	m = 0.5634f;
	//	b = -112.11f;
	//} else {
		m = 0.5f;
		b = -99.5f;
	//}
	float db = m * val + b;
	sprintf_s(buf, sizeof(buf), "%+4.1f db", db);
	return buf;
}

const char *PM10dbText(uint8_t val) {
	static char buf[16];
	float m, b;

	if (val < 0x14 || val > 0x3C) {
		sprintf_s(buf, sizeof(buf), "%02X OOR ?", val);
	} else {
		m = 0.5f;
		b = -10.0f;
		float db = m * (val - 0x14) + b;
		sprintf_s(buf, sizeof(buf), "%+4.1f db", db);
	}
	return buf;
}

const char *M20P0dbText(uint8_t val) {
	static char buf[16];
	float m, b;

	if (val > 0x28) {
		sprintf_s(buf, sizeof(buf), "%02X OOR ?", val);
	} else {
		m = 0.5f;
		b = -20.0f;
		float db = m * (val)+b;
		sprintf_s(buf, sizeof(buf), "%+4.1f db", db);
	}
	return buf;
}

const char *M10P10dbText(uint8_t val) {
	static char buf[16];
	float m, b;

	if (val < 0x14 || val > 0x3C) {
		sprintf_s(buf, sizeof(buf), "%02X OOR ?", val);
	} else {
		m = 0.5f;
		b = -10.0f;
		float db = m * (val - 0x14) + b;
		sprintf_s(buf, sizeof(buf), "%+4.1f db", db);
	}
	return buf;
}

const char *BalanceText(uint8_t val) {
	static char buf[16];
	float m, b;

	if (val > 0x28) {
		sprintf_s(buf, sizeof(buf), "%02X OOR ?", val);
	} else {
		m = 0.5f;
		b = -20.0f;
		float lcr = m * (val + b);
		sprintf_s(buf, sizeof(buf), "%+3.1f L-C-R", lcr);
	}
	return buf;
}

const char *M4To0Text(uint8_t val) {
	static char buf[16];

	if (val > 0x04) {
		sprintf_s(buf, sizeof(buf), "%02X OOR ?", val);
	} else {
		sprintf_s(buf, sizeof(buf), "%u", (int8_t)val - 4);
	}
	return buf;
}

const char *M5toP5Text(uint8_t val) {
	static char buf[16];

	if (val > 0x0A) {
		sprintf_s(buf, sizeof(buf), "%02X OOR ?", val);
	} else {
		sprintf_s(buf, sizeof(buf), "%+d", (int8_t)val - 5);
	}
	return buf;
}

const char *ZeroTo160msText(uint8_t val) {
	static char buf[16];

	if (val > 0xA0) {
		sprintf_s(buf, sizeof(buf), "%02X OOR ?", val);
	} else {
		sprintf_s(buf, sizeof(buf), "%u ms", val);
	}
	return buf;
}

const char *ZeroTo5msText(uint8_t val) {
	static char buf[16];
	float m, b;

	if (val > 0x0A) {
		sprintf_s(buf, sizeof(buf), "%02X OOR ?", val);
	} else {
		m = 0.5f;
		b = 0;
		float delay = m * (val + b);
		sprintf_s(buf, sizeof(buf), "%+3.1f ms", delay);
	}
	return buf;
}
const char *ZeroTo30msText(uint8_t val) {
	static char buf[16];
	float m, b;

	if (val > 0x3C) {
		sprintf_s(buf, sizeof(buf), "%02X OOR ?", val);
	} else {
		m = 0.5f;
		b = 0;
		float delay = m * (val + b);
		sprintf_s(buf, sizeof(buf), "%+4.1f ms", delay);
	}
	return buf;
}
