package com.mantz_it.guitartunerlibrary;

import android.content.SharedPreferences;
import android.util.Log;



import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;

/**
 * <h1>Wear Guitar Tuner - Preference Synchronization Helper</h1>
 *
 * Module:      PreferenceSyncHelper.java
 * Description: This class contains a collection of static helper functions to synchronize shared
 *              preferences between a Android smartphone and a wearable device running Android Wear
 *
 * @author Dennis Mantz
 *
 * Copyright (C) 2014 Dennis Mantz
 * License: http://www.gnu.org/licenses/gpl.html GPL version 2 or higher
 *
 * This library 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 library 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 library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */
public class PreferenceSyncHelper {
	private static final String LOGTAG = "PreferenceSyncHelper";

	/**
	 * Will synchronize a boolean preference to the other device by using the Wearable MessageAPI.
	 * Note: synchronization might fail even if this method returns true. Don't rely on this mechanism.
	 *
	 * @param googleApiClient		connected instance of the Google API Client to send a message
	 * @param nodeID				node id of the other device
	 * @param prefKey				key of the preference that should be synchronized
	 * @param newValue				new value of the preference
	 * @return true if the message was sent successfully. This does not guarantee that the other device has received the msg
	 */

	/**
	 * Will synchronize an integer preference to the other device by using the Wearable MessageAPI.
	 * Note: synchronization might fail even if this method returns true. Don't rely on this mechanism.
	 *
	 * @param googleApiClient		connected instance of the Google API Client to send a message
	 * @param nodeID				node id of the other device
	 * @param prefKey				key of the preference that should be synchronized
	 * @param newValue				new value of the preference
	 * @return true if the message was sent successfully. This does not guarantee that the other device has received the msg
	 */


	/**
	 * Will synchronize a float preference to the other device by using the Wearable MessageAPI.
	 * Note: synchronization might fail even if this method returns true. Don't rely on this mechanism.
	 *
	 * @param googleApiClient		connected instance of the Google API Client to send a message
	 * @param nodeID				node id of the other device
	 * @param prefKey				key of the preference that should be synchronized
	 * @param newValue				new value of the preference
	 * @return true if the message was sent successfully. This does not guarantee that the other device has received the msg
	 */


	/**
	 * Will synchronize a long preference to the other device by using the Wearable MessageAPI.
	 * Note: synchronization might fail even if this method returns true. Don't rely on this mechanism.
	 *
	 * @param googleApiClient		connected instance of the Google API Client to send a message
	 * @param nodeID				node id of the other device
	 * @param prefKey				key of the preference that should be synchronized
	 * @param newValue				new value of the preference
	 * @return true if the message was sent successfully. This does not guarantee that the other device has received the msg
	 */

	/**
	 * Will synchronize a string preference to the other device by using the Wearable MessageAPI.
	 * Note: synchronization might fail even if this method returns true. Don't rely on this mechanism.
	 *
	 * @param googleApiClient		connected instance of the Google API Client to send a message
	 * @param nodeID				node id of the other device
	 * @param prefKey				key of the preference that should be synchronized
	 * @param newValue				new value of the preference
	 * @return true if the message was sent successfully. This does not guarantee that the other device has received the msg
	 */


	/**
	 * Will synchronize a preference to the other device by using the Wearable MessageAPI.
	 * Note: synchronization might fail even if this method returns true. Don't rely on this mechanism.
	 * Don't use this method but the above wrapper methods instead!
	 *
	 * @param googleApiClient		connected instance of the Google API Client to send a message
	 * @param nodeID				node id of the other device
	 * @param prefKey				key of the preference that should be synchronized
	 * @param type					lowercase type of the preference (e.g. "string", "long", or "boolean")
	 * @param newValue				new value of the preference encoded as byte array
	 * @return true if the message was sent successfully. This does not guarantee that the other device has received the msg
	 */


		// Send it to the handheld device:


	/**
	 * This method will handle the reception of a sync message which was sent by the other device
	 * (using above methods)
	 *
	 * @param edit			a preference editor to update the received preference value
	 * @param messagePath	the message path that was associated with the message (containing the preference key and type)
	 * @param messageData	data of the message
	 * @return true if the preference was successfully extracted and updated from the message
	 */
	public static boolean handleSyncMessage(SharedPreferences.Editor edit, String messagePath, byte[] messageData) {
		String[] splitPath = messagePath.split("/");
		String type = splitPath[2];
		String prefKey = splitPath[3];
		String newValue = null;
		if(type.equals("boolean")) {
			Boolean newBool = messageData[0] > 0;
			newValue = "" + newBool;
			edit.putBoolean(prefKey, newBool);
		} else if(type.equals("integer")) {
			Integer newInt = ByteBuffer.wrap(messageData).getInt();
			newValue = "" + newInt;
			edit.putInt(prefKey, newInt);
		} else if(type.equals("long")) {
			Long newLong = ByteBuffer.wrap(messageData).getLong();
			newValue = "" + newLong;
			edit.putLong(prefKey, newLong);
		} else if(type.equals("float")) {
			Float newFloat = ByteBuffer.wrap(messageData).getFloat();
			newValue = "" + newFloat;
			edit.putFloat(prefKey, newFloat);
		} else if(type.equals("string")) {
			try {
				newValue = new String(messageData, "UTF-8");
				edit.putString(prefKey, newValue);
			} catch (UnsupportedEncodingException e) {
				Log.e(LOGTAG, "handleSyncMessage: Failed to extract String: " + e.getMessage());
			}
		} else {
			Log.d(LOGTAG, "handleSyncMessage: Received a syncPref message with unknown type: " + type);
			return false;
		}
		Log.d(LOGTAG, "handleSyncMessage: Received a syncPref message. Type is " + type + ". New value is " + newValue);
		edit.apply();
		return true;
	}
}
