//---------------------------------------------------------------------------------------
// Sonos Utility Functions - use control API to stop/start speakers
//---------------------------------------------------------------------------------------
'use strict'

// Install relevant utilities
const SmartState  = require('@katesthings/smartstate');

// Install relevant node packages
const axios = require("axios");


// Store stateful Sonos data in DynamoDB home setting table
async function getSonosData( key ) {
	return await SmartState.getHomeMode( 'niwot', 'sonos-' + key );
};

async function putSonosData( key, value ) {
	await SmartState.putHomeMode( 'niwot', 'sonos-' + key, value );
};

// Refresh access token
async function refreshToken() {

	// declare access token variable to be returned
	let accessToken;
	
	try {
		// create axios sonos control object
		const refreshToken = await getSonosData('refresh-token');
		console.log('refreshToken - retrieved refresh token: ', refreshToken);
			
		const urlToken = 'https://api.sonos.com/login/v3/oauth/access';

		const params = new URLSearchParams();
		params.append('grant_type', 'refresh_token');
		params.append('refresh_token', refreshToken);
		// params.append('redirect_uri', 'https%3A%2F%2F00t156cqe1.execute-api.us-west-2.amazonaws.com%2Fdev%2Fauth-callback');
		console.log('refreshToken - initialized parameters: ', params);
	
		const config = {
			headers: {
				'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8',
				'Authorization': 'Basic ZDMxM2EyYTAtOTYwZS00ODFmLTlmYzctM2MwMmU0MzY2OTU1OjNhY2ZkZmQ5LTI3YzQtNGE3NC05NzhkLWUyN2ZlZmE0NWJkMg=='
			}
		}
		
		console.log('refreshToken - refreshing access token');
		axios.post(urlToken, params, config).then((result) => {
			console.log('refreshToken - Success!  Data: ', result.data);
			
			// store tokens in DynamoDB home settings file
			const token_data = result.data;
			accessToken = token_data.access_token;
			
			putSonosData( 'token-time', new Date() );
			putSonosData( 'access-token', token_data.access_token );
			putSonosData( 'refresh-token', token_data.refresh_token );
			putSonosData( 'expires-in', token_data.expires_in.toString() );
			
			// putSonosToken( tokenData );
		}).catch((err) => { console.log('refreshToken - error refreshing token: ', err); })
	} catch(err) { console.log('refreshToken - error getting refresh token from DynamoDB: ', err) }	
	
	// return refreshed access token
	return accessToken;
};

// Get access token
async function getAccessToken() {
	
	// declare access token variable to be returned
	let accessToken;

	try {
		// create axios sonos control object
		console.log('getAccessToken - getting Sonos data from DyanmoDB');
		accessToken = await getSonosData('access-token');
		const tokenTime = new Date( await getSonosData( 'token-time' ) );
		const expiresIn = await getSonosData( 'expires-in' );

		// check to see if token has expired
		const currentTime: any = new Date();
		const elapsedTime = (currentTime.getTime() - tokenTime.getTime()) / 1000;
		console.log('getAccessToken - token-time: ', tokenTime, ', expires-in: ', expiresIn, ', time gap: ', elapsedTime );
		if ( elapsedTime > expiresIn ) {
			console.log('getAccessToken - token expired, need to refresh: ', elapsedTime);
			accessToken = await refreshToken();
		}
	} catch(err) { console.log('getAccessToken - error getting refresh token from DynamoDB: ', err) }	
	
	return accessToken;
};


// Control playback on Sonos speakers
async function controlSpeakers(context, speakers, command) {
	  	
	try {
		// create axios sonos control object
		// const access_token = await SmartState.getHomeMode('niwot', 'sonos-access-token');
		const access_token = await getAccessToken();
		const sonosControl = axios.create({
			baseURL: 'https://api.ws.sonos.com/control/api/v1',
			timeout: 5000,
			headers: {
				'Content-Type': 'application/json',
				'Authorization': 'Bearer ' + access_token
			}
		});

		// get household id
		console.log('controlSpeakers - getting households');
		sonosControl.get('households').then((result) => {
			const householdId = result.data.households[0].id;			
			console.log('controlSpeakers - household ID: ', householdId);
			// putSonosData( 'household-id', idHousehold );

			// get sonos groups and devices
			sonosControl.get('households/' + householdId + '/groups').then((result) => {
				const sonosPlayers = result.data.players;
				const sonosGroups  = result.data.groups;

				// pause all specified speakers
				// for (const speaker of context.config.roomSpeakers) {
				const speakerDevices = context.config[speakers];
				for (const speaker of speakerDevices) {
					const speakerId = speaker.deviceConfig.deviceId;
					context.api.devices.get(speakerId).then((speakerInfo) => {
						const speakerName = speakerInfo.name;
						console.log('controlSpeakers - find speaker: ', speakerName, ', speakerId: ', speakerId);

						// find player that include selected speaker
						const player = sonosPlayers.find(speaker => speaker.name === speakerName);
						console.log('controlSpeakers - player found: ', player, ', id: ', player.id);

						// find groups that include that player
						// console.log('controlSpeakers - Sonos groups: ', sonosGroups);
						for (const group of sonosGroups) {
							const groupPlayers = group.playerIds;
							// console.log('controlSpeakers - playerIds: ', groupPlayers);
							
							// if player included in group
							if (groupPlayers.indexOf(player.id) > -1) {
								const urlControl = '/groups/' + group.id + '/playback/' + command;
								console.log('controlSpeakers - command: ', command, ', urlControl: ', urlControl);
								// sonosControl.post(urlControl);
								sonosControl.post(urlControl).then((result) => {
									console.log('controlSpeakers - Success!  Data: ', result.data);;
								}).catch((err) => { console.log('controlSpeakers - error controlling speaker: ', err, ', command: ', command); })
							}
						}
					})
				}
			}).catch((err) => { console.log('controlSpeakers - error getting groups/speakers: ', err); })
		}).catch((err) => { console.log('controlSpeakers - error getting household(s): ', err); })
	} catch(err) { console.log('controlSpeakers - error controlling Sonos: ', err); }
};


// export external modules
// module.exports.getAccessToken = getAccessToken
module.exports.controlSpeakers = controlSpeakers
