/*
* This file is part of the Remote Sensor Actuator Interface (ReSAI).
*
* Copyright(c) Andreas Kipp, Frederic Siepmann
* http://opensource.cit-ec.de/projects/resai
*
* This file may be licensed under the terms of of the
* GNU Lesser General Public License Version 3 (the ``LGPL''),
* or (at your option) any later version.
*
* Software distributed under the License is distributed
* on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
* express or implied. See the LGPL for the specific language
* governing rights and limitations.
*
* You should have received a copy of the LGPL along with this
* program. If not, go to http://www.gnu.org/licenses/lgpl.html
* or write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The development of this software was supported by the
* Excellence Cluster EXC 277 Cognitive Interaction Technology.
* The Excellence Cluster EXC 277 is a grant of the Deutsche
* Forschungsgemeinschaft (DFG) in the context of the German
* Excellence Initiative.
*
*/

/**
 * Tab used to script behavior of the icub.
 *
 * @author akipp
 */

package de.unibi.airobots.resaidroid.tabactivities;

import java.util.ArrayList;

import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.SeekBar;
import android.widget.Spinner;
import android.widget.TableRow;
import android.widget.TextView;
import de.unibi.airobots.resaidroid.R;
import de.unibi.airobots.resaidroid.constants.ServerConfig;
import de.unibi.airobots.resaidroid.helper.EasyDialog;
import de.unibi.airobots.resaidroid.tabactivities.template.TabTemplate;

public class TabScripter extends TabTemplate implements
		SeekBar.OnSeekBarChangeListener, OnItemSelectedListener {

	private Spinner m_ElementSpinner;
	private ArrayAdapter<CharSequence> m_adapterForElementSpinner;

	private Spinner m_ScriptSpinner;
	private ArrayAdapter<CharSequence> m_adapterForScriptSpinner;

	private SeekBar joint0, joint1, joint2, joint3, joint4, joint5;
	private SeekBar joint6, joint7, joint8, joint9, joint10;
	private SeekBar joint11, joint12, joint13, joint14, joint15;

	private SeekBar seekMoveDelay;
	private TextView txtMoveDelay;
	private EditText txtSpeech;

	private int joint0Offset = 0, joint1Offset = 0, joint2Offset = 0;
	private int joint3Offset = 0, joint4Offset = 0, joint5Offset = 0;
	private int joint6Offset = 0, joint7Offset = 0, joint8Offset = 0;
	private int joint9Offset = 0, joint10Offset = 0, joint11Offset = 0;
	private int joint12Offset = 0, joint13Offset = 0, joint14Offset = 0;
	private int joint15Offset = 0;

	private TableRow rowJoint0, rowJoint1, rowJoint2, rowJoint3, rowJoint4;
	private TableRow rowJoint5, rowJoint6, rowJoint7, rowJoint8, rowJoint9;
	private TableRow rowJoint10, rowJoint11, rowJoint12, rowJoint13;
	private TableRow rowJoint14, rowJoint15, rowSpeech;

	private Button btnTest, btnAdd, btnExecute, btnInterrupt;

	private ArrayList<String> scripts = new ArrayList<String>();

	private String selectedElement = null;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.scripter);

		// CREATE VIEW ELEMENTS
		initElementSpinner();
		initScriptSpinner();
		initValueFields();
		m_ScriptSpinner.setOnItemSelectedListener(this);
		m_ElementSpinner.setOnItemSelectedListener(this);

		txtMoveDelay = (TextView) findViewById(R.id.txtMoveDelay);
		seekMoveDelay = (SeekBar) findViewById(R.id.seekMoveDelay);
		seekMoveDelay.setOnSeekBarChangeListener(this);

		// INIT SEEKBAR SELECTION AND SLIDERS
		setAvaibleSeekBars("Head");
		setSliderMinMax();

		// REQUEST SCRIPTS
		sendScriptLine("get_scriptnames", false);

		// CREATE BUTTONS AND THEIR LISTENERS
		btnTest = (Button) findViewById(R.id.btnTest);
		btnTest.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				if (m_ElementSpinner.getSelectedItem() != null) {
					sendScriptLine("test", true);
				} else {
					EasyDialog.makeToast(getApplicationContext(),
							"Please select an element first!");
				}
			}
		});

		btnInterrupt = (Button) findViewById(R.id.btnInterrupt);
		btnInterrupt.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				sendScriptLine("interrupt", false);
			}
		});

		btnAdd = (Button) findViewById(R.id.btnAdd);
		btnAdd.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				if (m_ElementSpinner.getSelectedItem() != null
						&& m_ScriptSpinner.getSelectedItem() != null) {
					sendScriptLine("add", true);
				} else {
					EasyDialog.makeToast(getApplicationContext(),
							"Please select a script and element first!");
				}
			}

		});

		btnExecute = (Button) findViewById(R.id.btnExecute);
		btnExecute.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				if (m_ScriptSpinner.getSelectedItem() != null) {

					sendScriptLine("execute_script", false);

				} else {
					EasyDialog.makeToast(getApplicationContext(),
							"Please select a script first!");
				}
			}
		});
	}

	@Override
	protected void onResume() {
		// TODO Auto-generated method stub
		super.onResume();

		// REQUEST SCRIPTS
		sendScriptLine("get_scriptnames", false);
	}

	@Override
	public void processProperties() {
		messageHandler.post(new Runnable() {
			public void run() {
				try {
					synchronized (receivedProperties) {
						if (receivedProperties
								.containsKey("ScripterThread_ACTION")) {

							if (receivedProperties.get("ScripterThread_ACTION")
									.equals("scriptnames")) {

								scripts.clear();
								for (String prop : receivedProperties.keySet()) {
									if (prop.startsWith(
											"ScripterThread_SCRIPT_", 0)) {
										scripts.add(receivedProperties
												.get(prop));
									}
								}
								initScriptSpinner();

							} else if (receivedProperties.get(
									"ScripterThread_ACTION").equals("error")) {

								EasyDialog
										.makeToast(
												getApplicationContext(),
												receivedProperties
														.get("ScripterThread_ERROR_MESSAGE"));
							}
						}
					}
				} catch (Exception e) {
					// TODO: handle exception
					Log.i(TAG, "###ERROR " + e.getMessage());
				}
			}
		});
	}

	private void setAvaibleSeekBars(String visElement) {

		rowJoint0.setVisibility(View.GONE);
		rowJoint1.setVisibility(View.GONE);
		rowJoint2.setVisibility(View.GONE);
		rowJoint3.setVisibility(View.GONE);
		rowJoint4.setVisibility(View.GONE);
		rowJoint5.setVisibility(View.GONE);
		rowJoint6.setVisibility(View.GONE);
		rowJoint7.setVisibility(View.GONE);
		rowJoint8.setVisibility(View.GONE);
		rowJoint9.setVisibility(View.GONE);
		rowJoint10.setVisibility(View.GONE);
		rowJoint11.setVisibility(View.GONE);
		rowJoint12.setVisibility(View.GONE);
		rowJoint13.setVisibility(View.GONE);
		rowJoint14.setVisibility(View.GONE);
		rowJoint15.setVisibility(View.GONE);
		rowSpeech.setVisibility(View.GONE);

		if (visElement.equals("Head")) {
			rowJoint0.setVisibility(View.VISIBLE);
			rowJoint1.setVisibility(View.VISIBLE);
			rowJoint2.setVisibility(View.VISIBLE);
			rowJoint3.setVisibility(View.VISIBLE);
			rowJoint4.setVisibility(View.VISIBLE);
			rowJoint5.setVisibility(View.VISIBLE);
		}

		if (visElement.equals("Torso")) {
			rowJoint0.setVisibility(View.VISIBLE);
			rowJoint1.setVisibility(View.VISIBLE);
			rowJoint2.setVisibility(View.VISIBLE);
		}

		if (visElement.equals("Left_Arm") || visElement.equals("Right_Arm")) {
			rowJoint0.setVisibility(View.VISIBLE);
			rowJoint1.setVisibility(View.VISIBLE);
			rowJoint2.setVisibility(View.VISIBLE);
			rowJoint3.setVisibility(View.VISIBLE);
			rowJoint4.setVisibility(View.VISIBLE);
			rowJoint5.setVisibility(View.VISIBLE);
			rowJoint6.setVisibility(View.VISIBLE);
			rowJoint7.setVisibility(View.VISIBLE);
			rowJoint8.setVisibility(View.VISIBLE);
			rowJoint9.setVisibility(View.VISIBLE);
			rowJoint10.setVisibility(View.VISIBLE);
			rowJoint11.setVisibility(View.VISIBLE);
			rowJoint12.setVisibility(View.VISIBLE);
			rowJoint13.setVisibility(View.VISIBLE);
			rowJoint14.setVisibility(View.VISIBLE);
			rowJoint15.setVisibility(View.VISIBLE);
		}

		if (visElement.equals("Left_Leg") || visElement.equals("Right_Leg")) {
			rowJoint0.setVisibility(View.VISIBLE);
			rowJoint1.setVisibility(View.VISIBLE);
			rowJoint2.setVisibility(View.VISIBLE);
			rowJoint3.setVisibility(View.VISIBLE);
			rowJoint4.setVisibility(View.VISIBLE);
			rowJoint5.setVisibility(View.VISIBLE);
		}

		if (visElement.equals("Speech")) {
			rowSpeech.setVisibility(View.VISIBLE);
		}

	}

	private void setSliderMinMax() {
		if (selectedElement == null) {
			return;
		}

		if (selectedElement.equals("Head")) {
			joint0Offset = 40;
			joint0.setMax(30 + joint0Offset);
			joint0.setProgress(35);

			joint1Offset = 70;
			joint1.setMax(60 + joint1Offset);
			joint1.setProgress(65);

			joint2Offset = 55;
			joint2.setMax(55 + joint2Offset);
			joint2.setProgress(55);

			joint3Offset = 35;
			joint3.setMax(15 + joint3Offset);
			joint3.setProgress(25);

			joint4Offset = 50;
			joint4.setMax(52 + joint4Offset);
			joint4.setProgress(51);

			joint5Offset = 0;
			joint5.setMax(90 + joint5Offset);
			joint5.setProgress(45);
		}

		if (selectedElement.equals("Torso")) {
			joint0Offset = 50;
			joint0.setMax(50 + joint0Offset);
			joint0.setProgress(50);

			joint1Offset = 30;
			joint1.setMax(30 + joint1Offset);
			joint1.setProgress(30);

			joint2Offset = 10;
			joint2.setMax(70 + joint2Offset);
			joint2.setProgress(40);
		}

		if (selectedElement.equals("Left_Arm")
				|| selectedElement.equals("Right_Arm")) {
			joint0Offset = 95;
			joint0.setMax(10 + joint0Offset);
			joint0.setProgress(52);

			joint1Offset = 0;
			joint1.setMax(161 + joint1Offset);
			joint1.setProgress(80);

			joint2Offset = 22;
			joint2.setMax(95 + joint2Offset);
			joint2.setProgress(63);

			joint3Offset = 15;
			joint3.setMax(106 + joint3Offset);
			joint3.setProgress(60);

			joint4Offset = 90;
			joint4.setMax(90 + joint4Offset);
			joint4.setProgress(90);

			joint5Offset = 90;
			joint5.setMax(0 + joint5Offset);
			joint5.setProgress(45);

			joint6Offset = 20;
			joint6.setMax(40 + joint6Offset);
			joint6.setProgress(30);

			joint7Offset = 0;
			joint7.setMax(60 + joint7Offset);
			joint7.setProgress(30);

			joint8Offset = 0;
			joint8.setMax(90 + joint8Offset);
			joint8.setProgress(45);

			joint9Offset = 0;
			joint9.setMax(90 + joint9Offset);
			joint9.setProgress(45);

			joint10Offset = 0;
			joint10.setMax(90 + joint10Offset);
			joint10.setProgress(45);

			joint11Offset = 0;
			joint11.setMax(90 + joint11Offset);
			joint11.setProgress(45);

			joint12Offset = 0;
			joint12.setMax(90 + joint12Offset);
			joint12.setProgress(45);

			joint13Offset = 0;
			joint13.setMax(90 + joint13Offset);
			joint13.setProgress(45);

			joint14Offset = 0;
			joint14.setMax(90 + joint14Offset);
			joint14.setProgress(45);

			joint15Offset = 0;
			joint15.setMax(115 + joint15Offset);
			joint15.setProgress(57);
		}

		if (selectedElement.equals("Left_Leg")
				|| selectedElement.equals("Right_Leg")) {
			joint0Offset = 30;
			joint0.setMax(90 + joint0Offset);
			joint0.setProgress(60);

			joint1Offset = 0;
			joint1.setMax(90 + joint1Offset);
			joint1.setProgress(45);

			joint2Offset = 80;
			joint2.setMax(78 + joint2Offset);
			joint2.setProgress(79);

			joint3Offset = 125;
			joint3.setMax(15 + joint3Offset);
			joint3.setProgress(70);

			joint4Offset = 20;
			joint4.setMax(44 + joint4Offset);
			joint4.setProgress(32);

			joint5Offset = 22;
			joint5.setMax(22 + joint5Offset);
			joint5.setProgress(22);
		}
	}

	private void initValueFields() {
		// CONNECT JOINTS TO TEXT
		joint0 = (SeekBar) findViewById(R.id.seekJoint0);
		joint0.setOnSeekBarChangeListener(this);
		rowJoint0 = (TableRow) findViewById(R.id.rowJoint0);

		joint1 = (SeekBar) findViewById(R.id.seekJoint1);
		joint1.setOnSeekBarChangeListener(this);
		rowJoint1 = (TableRow) findViewById(R.id.rowJoint1);

		joint2 = (SeekBar) findViewById(R.id.seekJoint2);
		joint2.setOnSeekBarChangeListener(this);
		rowJoint2 = (TableRow) findViewById(R.id.rowJoint2);

		joint3 = (SeekBar) findViewById(R.id.seekJoint3);
		joint3.setOnSeekBarChangeListener(this);
		rowJoint3 = (TableRow) findViewById(R.id.rowJoint3);

		joint4 = (SeekBar) findViewById(R.id.seekJoint4);
		joint4.setOnSeekBarChangeListener(this);
		rowJoint4 = (TableRow) findViewById(R.id.rowJoint4);

		joint5 = (SeekBar) findViewById(R.id.seekJoint5);
		joint5.setOnSeekBarChangeListener(this);
		rowJoint5 = (TableRow) findViewById(R.id.rowJoint5);

		joint6 = (SeekBar) findViewById(R.id.seekJoint6);
		joint6.setOnSeekBarChangeListener(this);
		rowJoint6 = (TableRow) findViewById(R.id.rowJoint6);

		joint7 = (SeekBar) findViewById(R.id.seekJoint7);
		joint7.setOnSeekBarChangeListener(this);
		rowJoint7 = (TableRow) findViewById(R.id.rowJoint7);

		joint8 = (SeekBar) findViewById(R.id.seekJoint8);
		joint8.setOnSeekBarChangeListener(this);
		rowJoint8 = (TableRow) findViewById(R.id.rowJoint8);

		joint9 = (SeekBar) findViewById(R.id.seekJoint9);
		joint9.setOnSeekBarChangeListener(this);
		rowJoint9 = (TableRow) findViewById(R.id.rowJoint9);

		joint10 = (SeekBar) findViewById(R.id.seekJoint10);
		joint10.setOnSeekBarChangeListener(this);
		rowJoint10 = (TableRow) findViewById(R.id.rowJoint10);

		joint11 = (SeekBar) findViewById(R.id.seekJoint11);
		joint11.setOnSeekBarChangeListener(this);
		rowJoint11 = (TableRow) findViewById(R.id.rowJoint11);

		joint12 = (SeekBar) findViewById(R.id.seekJoint12);
		joint12.setOnSeekBarChangeListener(this);
		rowJoint12 = (TableRow) findViewById(R.id.rowJoint12);

		joint13 = (SeekBar) findViewById(R.id.seekJoint13);
		joint13.setOnSeekBarChangeListener(this);
		rowJoint13 = (TableRow) findViewById(R.id.rowJoint13);

		joint14 = (SeekBar) findViewById(R.id.seekJoint14);
		joint14.setOnSeekBarChangeListener(this);
		rowJoint14 = (TableRow) findViewById(R.id.rowJoint14);

		joint15 = (SeekBar) findViewById(R.id.seekJoint15);
		joint15.setOnSeekBarChangeListener(this);
		rowJoint15 = (TableRow) findViewById(R.id.rowJoint15);

		rowSpeech = (TableRow) findViewById(R.id.rowSpeech);
		txtSpeech = (EditText) findViewById(R.id.txtSpeech);

	}

	public void initElementSpinner() {
		// ELEMENT SPINNER
		m_ElementSpinner = (Spinner) findViewById(R.id.spinnerElement);
		m_adapterForElementSpinner = new ArrayAdapter<CharSequence>(this,
				android.R.layout.simple_spinner_item);
		m_adapterForElementSpinner
				.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
		m_ElementSpinner.setAdapter(m_adapterForElementSpinner);
		// TODO Add for safety purpose?
		// m_adapterForElementSpinner.add("<Select Element>");
		m_adapterForElementSpinner.add("Head");
		m_adapterForElementSpinner.add("Left_Arm");
		m_adapterForElementSpinner.add("Right_Arm");
		m_adapterForElementSpinner.add("Torso");
		m_adapterForElementSpinner.add("Left_Leg");
		m_adapterForElementSpinner.add("Right_Leg");
		m_adapterForElementSpinner.add("Speech");
		m_adapterForElementSpinner.add("Home_All");
	}

	public void initScriptSpinner() {
		// SCRIPT SPINNER
		m_ScriptSpinner = (Spinner) findViewById(R.id.spinnerScript);

		m_adapterForScriptSpinner = new ArrayAdapter<CharSequence>(this,
				android.R.layout.simple_spinner_item);

		m_adapterForScriptSpinner.clear();

		m_adapterForScriptSpinner
				.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
		m_ScriptSpinner.setAdapter(m_adapterForScriptSpinner);
		for (String scriptname : scripts) {
			m_adapterForScriptSpinner.add(scriptname);
		}

		m_ScriptSpinner.setOnItemSelectedListener(this);
	}

	public void onProgressChanged(SeekBar seekBar, int progress,
			boolean fromTouch) {
		if (seekBar.equals(joint0)) {
			TextView txtJoint0 = (TextView) findViewById(R.id.seekValue0);
			txtJoint0.setText(String.valueOf(progress - joint0Offset));
		}

		if (seekBar.equals(joint1)) {
			TextView txtJoint1 = (TextView) findViewById(R.id.seekValue1);
			txtJoint1.setText(String.valueOf(progress - joint1Offset));
		}

		if (seekBar.equals(joint2)) {
			TextView txtJoint2 = (TextView) findViewById(R.id.seekValue2);
			txtJoint2.setText(String.valueOf(progress - joint2Offset));
		}

		if (seekBar.equals(joint3)) {
			TextView txtJoint3 = (TextView) findViewById(R.id.seekValue3);
			txtJoint3.setText(String.valueOf(progress - joint3Offset));
		}

		if (seekBar.equals(joint4)) {
			TextView txtJoint4 = (TextView) findViewById(R.id.seekValue4);
			txtJoint4.setText(String.valueOf(progress - joint4Offset));
		}

		if (seekBar.equals(joint5)) {
			TextView txtJoint5 = (TextView) findViewById(R.id.seekValue5);
			txtJoint5.setText(String.valueOf(progress - joint5Offset));
		}

		if (seekBar.equals(joint6)) {
			TextView txtJoint6 = (TextView) findViewById(R.id.seekValue6);
			txtJoint6.setText(String.valueOf(progress - joint6Offset));
		}

		if (seekBar.equals(joint7)) {
			TextView txtJoint7 = (TextView) findViewById(R.id.seekValue7);
			txtJoint7.setText(String.valueOf(progress - joint7Offset));
		}

		if (seekBar.equals(joint8)) {
			TextView txtJoint8 = (TextView) findViewById(R.id.seekValue8);
			txtJoint8.setText(String.valueOf(progress - joint8Offset));
		}

		if (seekBar.equals(joint9)) {
			TextView txtJoint9 = (TextView) findViewById(R.id.seekValue9);
			txtJoint9.setText(String.valueOf(progress - joint9Offset));
		}

		if (seekBar.equals(joint10)) {
			TextView txtJoint10 = (TextView) findViewById(R.id.seekValue10);
			txtJoint10.setText(String.valueOf(progress - joint10Offset));
		}

		if (seekBar.equals(joint11)) {
			TextView txtJoint11 = (TextView) findViewById(R.id.seekValue11);
			txtJoint11.setText(String.valueOf(progress - joint11Offset));
		}

		if (seekBar.equals(joint12)) {
			TextView txtJoint12 = (TextView) findViewById(R.id.seekValue12);
			txtJoint12.setText(String.valueOf(progress - joint12Offset));
		}

		if (seekBar.equals(joint13)) {
			TextView txtJoint13 = (TextView) findViewById(R.id.seekValue13);
			txtJoint13.setText(String.valueOf(progress - joint13Offset));
		}

		if (seekBar.equals(joint14)) {
			TextView txtJoint14 = (TextView) findViewById(R.id.seekValue14);
			txtJoint14.setText(String.valueOf(progress - joint14Offset));
		}

		if (seekBar.equals(joint15)) {
			TextView txtJoint15 = (TextView) findViewById(R.id.seekValue15);
			txtJoint15.setText(String.valueOf(progress - joint15Offset));
		}

		if (seekBar.equals(seekMoveDelay)) {
			txtMoveDelay.setText(String.valueOf(progress));
		}

	}

	public void onStartTrackingTouch(SeekBar seekBar) {
	}

	public void onStopTrackingTouch(SeekBar seekBar) {
	}

	@Override
	public void onItemSelected(AdapterView<?> parent, View view, int pos,
			long id) {
		if (parent.equals(m_ElementSpinner)) {
			selectedElement = parent.getItemAtPosition(pos).toString();
			setAvaibleSeekBars(selectedElement);
			setSliderMinMax();
		}
	}

	@Override
	public void onNothingSelected(AdapterView<?> parent) {

	}

	private void sendScriptLine(String _action, boolean _addValues) {
		addProperty("TAG", "ScripterThread");
		addProperty("ScripterThread", "True");
		addProperty("ACTION", _action);
		addProperty("MOVE_DELAY", String.valueOf(seekMoveDelay.getProgress()));
		if (m_ScriptSpinner.getSelectedItem() != null) {
			addProperty(
					"SCRIPT",
					m_ScriptSpinner.getItemAtPosition(
							m_ScriptSpinner.getSelectedItemPosition())
							.toString());
		}
		if (_addValues) {

			String element = m_ElementSpinner.getItemAtPosition(
					m_ElementSpinner.getSelectedItemPosition()).toString();
			addProperty("ELEMENT", element);

			if (element.equals("Speech")) {
				addProperty("TYPES", "speech");
				addProperty("speech", txtSpeech.getText().toString());
			} else {
				addProperty("TYPES", "joints");
				addJoints();
			}
		}
		sendMessage(ServerConfig.RECIPIENT_FULL);
	}

	private void addJoints() {
		addProperty("joint0",
				String.valueOf(joint0.getProgress() - joint0Offset));
		addProperty("joint1",
				String.valueOf(joint1.getProgress() - joint1Offset));
		addProperty("joint2",
				String.valueOf(joint2.getProgress() - joint2Offset));
		addProperty("joint3",
				String.valueOf(joint3.getProgress() - joint3Offset));
		addProperty("joint4",
				String.valueOf(joint4.getProgress() - joint4Offset));
		addProperty("joint5",
				String.valueOf(joint5.getProgress() - joint5Offset));
		addProperty("joint6",
				String.valueOf(joint6.getProgress() - joint6Offset));
		addProperty("joint7",
				String.valueOf(joint7.getProgress() - joint7Offset));
		addProperty("joint8",
				String.valueOf(joint8.getProgress() - joint8Offset));
		addProperty("joint9",
				String.valueOf(joint9.getProgress() - joint9Offset));
		addProperty("joint10",
				String.valueOf(joint10.getProgress() - joint10Offset));
		addProperty("joint11",
				String.valueOf(joint11.getProgress() - joint11Offset));
		addProperty("joint12",
				String.valueOf(joint12.getProgress() - joint12Offset));
		addProperty("joint13",
				String.valueOf(joint13.getProgress() - joint13Offset));
		addProperty("joint14",
				String.valueOf(joint14.getProgress() - joint14Offset));
		addProperty("joint15",
				String.valueOf(joint15.getProgress() - joint15Offset));
	}
}