/**
   Virtual function to update the UI widget objects
 */
QString ConfigGroundVehicleWidget::updateConfigObjectsFromWidgets()
{
    QString airframeType = "GroundVehicleCar";

    // Save the curve (common to all ground vehicle frames)
    UAVDataObject *mixer = dynamic_cast<UAVDataObject *>(getObjectManager()->getObject(QString("MixerSettings")));

    // set the throttle curves
    setThrottleCurve(mixer, VehicleConfig::MIXER_THROTTLECURVE1, m_aircraft->groundVehicleThrottle1->getCurve());
    setThrottleCurve(mixer, VehicleConfig::MIXER_THROTTLECURVE2, m_aircraft->groundVehicleThrottle2->getCurve());

    // All airframe types must start with "GroundVehicle"
    if (m_aircraft->groundVehicleType->currentText() == "Turnable (car)") {
        airframeType = "GroundVehicleCar";
        setupGroundVehicleCar(airframeType);
    } else if (m_aircraft->groundVehicleType->currentText() == "Differential (tank)") {
        airframeType = "GroundVehicleDifferential";
        setupGroundVehicleDifferential(airframeType);
    } else {
        airframeType = "GroundVehicleMotorcycle";
        setupGroundVehicleMotorcycle(airframeType);
    }

    return airframeType;
}
/**
 * @brief ConfigFixedWingWidget::updateConfigObjectsFromWidgets update the UI widget objects
 * @return airframe type
 */
SystemSettings::AirframeTypeOptions ConfigGroundVehicleWidget::updateConfigObjectsFromWidgets()
{
    SystemSettings::AirframeTypeOptions airframeType = SystemSettings::AIRFRAMETYPE_GROUNDVEHICLECAR;
	
	// Save the curve (common to all ground vehicle frames)
    MixerSettings *mixerSettings = MixerSettings::GetInstance(getObjectManager());
    Q_ASSERT(mixerSettings);

	// Remove Feed Forward, it is pointless on a ground vehicle:
    setMixerValue(mixerSettings, "FeedForward", 0.0);

    // set the throttle curves
    setThrottleCurve(mixerSettings, MixerSettings::MIXER1VECTOR_THROTTLECURVE1, m_aircraft->groundVehicleThrottle1->getCurve() );
    setThrottleCurve(mixerSettings, MixerSettings::MIXER1VECTOR_THROTTLECURVE2, m_aircraft->groundVehicleThrottle2->getCurve() );

	//All airframe types must start with "GroundVehicle"
	if (m_aircraft->groundVehicleType->currentText() == "Turnable (car)" ) {
        airframeType = SystemSettings::AIRFRAMETYPE_GROUNDVEHICLECAR;
		setupGroundVehicleCar(airframeType);
	} else if (m_aircraft->groundVehicleType->currentText() == "Differential (tank)") {
        airframeType = SystemSettings::AIRFRAMETYPE_GROUNDVEHICLEDIFFERENTIAL;
		setupGroundVehicleDifferential(airframeType);
	} else { // "Motorcycle"
        airframeType = SystemSettings::AIRFRAMETYPE_GROUNDVEHICLEMOTORCYCLE;
		setupGroundVehicleMotorcycle(airframeType);
	}

	return airframeType;
}
/**
   Helper function to
 */
QString ConfigCustomWidget::updateConfigObjectsFromWidgets()
{
    UAVDataObject *mixer = dynamic_cast<UAVDataObject *>(getObjectManager()->getObject(QString("MixerSettings")));

    Q_ASSERT(mixer);

    setThrottleCurve(mixer, VehicleConfig::MIXER_THROTTLECURVE1, m_aircraft->customThrottle1Curve->getCurve());
    setThrottleCurve(mixer, VehicleConfig::MIXER_THROTTLECURVE2, m_aircraft->customThrottle2Curve->getCurve());

    // Update the table:
    for (int channel = 0; channel < (int)VehicleConfig::CHANNEL_NUMELEM; channel++) {
        QComboBox *q = (QComboBox *)m_aircraft->customMixerTable->cellWidget(0, channel);
        if (q->currentText() == "Disabled") {
            setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_DISABLED);
        } else if (q->currentText() == "Motor") {
            setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_MOTOR);
        } else if (q->currentText() == "ReversableMotor") {
            setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_REVERSABLEMOTOR);
        } else if (q->currentText() == "Servo") {
            setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_SERVO);
        } else if (q->currentText() == "CameraRoll") {
            setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_CAMERAROLL);
        } else if (q->currentText() == "CameraPitch") {
            setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_CAMERAPITCH);
        } else if (q->currentText() == "CameraYaw") {
            setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_CAMERAYAW);
        } else if (q->currentText() == "Accessory0") {
            setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_ACCESSORY0);
        } else if (q->currentText() == "Accessory1") {
            setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_ACCESSORY1);
        } else if (q->currentText() == "Accessory2") {
            setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_ACCESSORY2);
        } else if (q->currentText() == "Accessory3") {
            setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_ACCESSORY3);
        } else if (q->currentText() == "Accessory4") {
            setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_ACCESSORY4);
        } else if (q->currentText() == "Accessory5") {
            setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_ACCESSORY5);
        }
        setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_THROTTLECURVE1,
                            m_aircraft->customMixerTable->item(1, channel)->text().toDouble());
        setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_THROTTLECURVE2,
                            m_aircraft->customMixerTable->item(2, channel)->text().toDouble());
        setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_ROLL,
                            m_aircraft->customMixerTable->item(3, channel)->text().toDouble());
        setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_PITCH,
                            m_aircraft->customMixerTable->item(4, channel)->text().toDouble());
        setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_YAW,
                            m_aircraft->customMixerTable->item(5, channel)->text().toDouble());
    }

    return "Custom";
}
/**
   Virtual function to update the UI widget objects
 */
QString ConfigFixedWingWidget::updateConfigObjectsFromWidgets()
{
    QString airframeType = "FixedWing";

    // Save the curve (common to all Fixed wing frames)
    UAVDataObject *mixer = dynamic_cast<UAVDataObject *>(getObjectManager()->getObject(QString("MixerSettings")));

    Q_ASSERT(mixer);

    // Set the throttle curve
    setThrottleCurve(mixer, VehicleConfig::MIXER_THROTTLECURVE1, m_aircraft->fixedWingThrottle->getCurve());

    // All airframe types must start with "FixedWing"
    if (m_aircraft->fixedWingType->currentText() == "Aileron") {
        airframeType = "FixedWing";
        setupFrameFixedWing(airframeType);
    } else if (m_aircraft->fixedWingType->currentText() == "Elevon") {
        airframeType = "FixedWingElevon";
        setupFrameElevon(airframeType);
    } else { // "Vtail"
        airframeType = "FixedWingVtail";
        setupFrameVtail(airframeType);
    }

    return airframeType;
}
/**
   Helper function to
 */
QString ConfigCustomWidget::updateConfigObjectsFromWidgets()
{
    UAVDataObject *system = dynamic_cast<UAVDataObject *>(getObjectManager()->getObject(QString("SystemSettings")));

    Q_ASSERT(system);

    QPointer<UAVObjectField> field = system->getField(QString("AirframeType"));

    // Do not allow changes until AirframeType == Custom
    // If user want to save custom mixer : first set AirframeType to 'Custom' without changes and next modify.
    if (field->getValue().toString() == "Custom") {
        UAVDataObject *mixer = dynamic_cast<UAVDataObject *>(getObjectManager()->getObject(QString("MixerSettings")));

        Q_ASSERT(mixer);

        setThrottleCurve(mixer, VehicleConfig::MIXER_THROTTLECURVE1, m_aircraft->customThrottle1Curve->getCurve());
        setThrottleCurve(mixer, VehicleConfig::MIXER_THROTTLECURVE2, m_aircraft->customThrottle2Curve->getCurve());

        GUIConfigDataUnion configData = getConfigData();
        resetActuators(&configData);

        // Update the table:
        for (int channel = 0; channel < (int)VehicleConfig::CHANNEL_NUMELEM; channel++) {
            QComboBox *q = (QComboBox *)m_aircraft->customMixerTable->cellWidget(0, channel);
            if (q->currentText() == "Disabled") {
                setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_DISABLED);
            } else if (q->currentText() == "Motor") {
                setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_MOTOR);
                if (configData.custom.Motor1 == 0) {
                    configData.custom.Motor1 = channel + 1;
                } else if (configData.custom.Motor2 == 0) {
                    configData.custom.Motor2 = channel + 1;
                } else if (configData.custom.Motor3 == 0) {
                    configData.custom.Motor3 = channel + 1;
                } else if (configData.custom.Motor4 == 0) {
                    configData.custom.Motor4 = channel + 1;
                } else if (configData.custom.Motor5 == 0) {
                    configData.custom.Motor5 = channel + 1;
                } else if (configData.custom.Motor6 == 0) {
                    configData.custom.Motor6 = channel + 1;
                } else if (configData.custom.Motor7 == 0) {
                    configData.custom.Motor7 = channel + 1;
                } else if (configData.custom.Motor8 == 0) {
                    configData.custom.Motor8 = channel + 1;
                }
            } else if (q->currentText() == "ReversableMotor") {
                setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_REVERSABLEMOTOR);
                if (configData.custom.RevMotor1 == 0) {
                    configData.custom.RevMotor1 = channel + 1;
                } else if (configData.custom.RevMotor2 == 0) {
                    configData.custom.RevMotor2 = channel + 1;
                } else if (configData.custom.RevMotor3 == 0) {
                    configData.custom.RevMotor3 = channel + 1;
                } else if (configData.custom.RevMotor4 == 0) {
                    configData.custom.RevMotor4 = channel + 1;
                } else if (configData.custom.RevMotor5 == 0) {
                    configData.custom.RevMotor5 = channel + 1;
                } else if (configData.custom.RevMotor6 == 0) {
                    configData.custom.RevMotor6 = channel;
                } else if (configData.custom.RevMotor7 == 0) {
                    configData.custom.RevMotor7 = channel;
                } else if (configData.custom.RevMotor8 == 0) {
                    configData.custom.RevMotor8 = channel;
                }
            } else if (q->currentText() == "Servo") {
                setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_SERVO);
                if (configData.custom.Servo1 == 0) {
                    configData.custom.Servo1 = channel + 1;
                } else if (configData.custom.Servo2 == 0) {
                    configData.custom.Servo2 = channel + 1;
                } else if (configData.custom.Servo3 == 0) {
                    configData.custom.Servo3 = channel + 1;
                } else if (configData.custom.Servo4 == 0) {
                    configData.custom.Servo4 = channel + 1;
                } else if (configData.custom.Servo5 == 0) {
                    configData.custom.Servo5 = channel + 1;
                } else if (configData.custom.Servo6 == 0) {
                    configData.custom.Servo6 = channel + 1;
                } else if (configData.custom.Servo7 == 0) {
                    configData.custom.Servo7 = channel + 1;
                } else if (configData.custom.Servo8 == 0) {
                    configData.custom.Servo8 = channel + 1;
                }
            } else if (q->currentText() == "CameraRoll") {
                setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_CAMERAROLL);
            } else if (q->currentText() == "CameraPitch") {
                setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_CAMERAPITCH);
            } else if (q->currentText() == "CameraYaw") {
                setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_CAMERAYAW);
            } else if (q->currentText() == "Accessory0") {
                setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_ACCESSORY0);
            } else if (q->currentText() == "Accessory1") {
                setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_ACCESSORY1);
            } else if (q->currentText() == "Accessory2") {
                setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_ACCESSORY2);
            } else if (q->currentText() == "Accessory3") {
                setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_ACCESSORY3);
            } else if (q->currentText() == "Accessory4") {
                setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_ACCESSORY4);
            } else if (q->currentText() == "Accessory5") {
                setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_ACCESSORY5);
            }
            setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_THROTTLECURVE1,
                                m_aircraft->customMixerTable->item(1, channel)->text().toDouble());
            setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_THROTTLECURVE2,
                                m_aircraft->customMixerTable->item(2, channel)->text().toDouble());
            setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_ROLL,
                                m_aircraft->customMixerTable->item(3, channel)->text().toDouble());
            setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_PITCH,
                                m_aircraft->customMixerTable->item(4, channel)->text().toDouble());
            setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_YAW,
                                m_aircraft->customMixerTable->item(5, channel)->text().toDouble());
        }
        setConfigData(configData);
    }
    return "Custom";
}
/**
 Helper function to update the UI widget objects
 */
SystemSettings::AirframeTypeOptions ConfigMultiRotorWidget::updateConfigObjectsFromWidgets()
{
    SystemSettings::AirframeTypeOptions airframeType = SystemSettings::AIRFRAMETYPE_FIXEDWING;
    QList<QString> motorList;

    MixerSettings *mixerSettings = MixerSettings::GetInstance(getObjectManager());
    Q_ASSERT(mixerSettings);

    // Curve is also common to all quads:
    setThrottleCurve(mixerSettings, MixerSettings::MIXER1VECTOR_THROTTLECURVE1, m_aircraft->multiThrottleCurve->getCurve() );

    if (m_aircraft->multirotorFrameType->itemData(m_aircraft->multirotorFrameType->currentIndex()) == SystemSettings::AIRFRAMETYPE_QUADP) {
        airframeType = SystemSettings::AIRFRAMETYPE_QUADP;
        setupQuad(true);
    } else if (m_aircraft->multirotorFrameType->itemData(m_aircraft->multirotorFrameType->currentIndex()) == SystemSettings::AIRFRAMETYPE_QUADX) {
        airframeType = SystemSettings::AIRFRAMETYPE_QUADX;
        setupQuad(false);
    } else if (m_aircraft->multirotorFrameType->itemData(m_aircraft->multirotorFrameType->currentIndex()) == SystemSettings::AIRFRAMETYPE_HEXA) {
        airframeType = SystemSettings::AIRFRAMETYPE_HEXA;
        setupHexa(true);
    } else if (m_aircraft->multirotorFrameType->itemData(m_aircraft->multirotorFrameType->currentIndex()) == SystemSettings::AIRFRAMETYPE_HEXAX) {
        airframeType = SystemSettings::AIRFRAMETYPE_HEXAX;
        setupHexa(false);
    } else if (m_aircraft->multirotorFrameType->itemData(m_aircraft->multirotorFrameType->currentIndex()) == SystemSettings::AIRFRAMETYPE_HEXACOAX) {
        airframeType = SystemSettings::AIRFRAMETYPE_HEXACOAX;

        //Show any config errors in GUI
        if (throwConfigError(6)) {
            return airframeType;
        }
        motorList << "VTOLMotorNW" << "VTOLMotorW" << "VTOLMotorNE" << "VTOLMotorE"
                  << "VTOLMotorS" << "VTOLMotorSE";
        setupMotors(motorList);

        // Motor 1 to 6, Y6 Layout:
        //     pitch   roll    yaw
        double mixer [8][3] = {
            {  0.5,  1, -1},
            {  0.5,  1,  1},
            {  0.5, -1, -1},
            {  0.5, -1,  1},
            { -1,    0, -1},
            { -1,    0,  1},
            {  0,    0,  0},
            {  0,    0,  0}
        };
        setupMultiRotorMixer(mixer);
        m_aircraft->mrStatusLabel->setText("Configuration OK");

    } else if (m_aircraft->multirotorFrameType->itemData(m_aircraft->multirotorFrameType->currentIndex()) == SystemSettings::AIRFRAMETYPE_OCTO) {
        airframeType = SystemSettings::AIRFRAMETYPE_OCTO;

        //Show any config errors in GUI
        if (throwConfigError(8)) {
            return airframeType;

        }
        motorList << "VTOLMotorN" << "VTOLMotorNE" << "VTOLMotorE" << "VTOLMotorSE"
                  << "VTOLMotorS" << "VTOLMotorSW" << "VTOLMotorW" << "VTOLMotorNW";
        setupMotors(motorList);
        // Motor 1 to 8:
        //     pitch   roll    yaw
        double mixer [8][3] = {
            {  1,  0, -1},
            {  1, -1,  1},
            {  0, -1, -1},
            { -1, -1,  1},
            { -1,  0, -1},
            { -1,  1,  1},
            {  0,  1, -1},
            {  1,  1,  1}
        };
        setupMultiRotorMixer(mixer);
        m_aircraft->mrStatusLabel->setText("Configuration OK");

    } else if (m_aircraft->multirotorFrameType->itemData(m_aircraft->multirotorFrameType->currentIndex()) == SystemSettings::AIRFRAMETYPE_OCTOV) {
        airframeType = SystemSettings::AIRFRAMETYPE_OCTOV;

        //Show any config errors in GUI
        if (throwConfigError(8)) {
            return airframeType;
        }
        motorList << "VTOLMotorN" << "VTOLMotorNE" << "VTOLMotorE" << "VTOLMotorSE"
                  << "VTOLMotorS" << "VTOLMotorSW" << "VTOLMotorW" << "VTOLMotorNW";
        setupMotors(motorList);
        // Motor 1 to 8:
        // IMPORTANT: Assumes evenly spaced engines
        //     pitch   roll    yaw
        double mixer [8][3] = {
            {  0.33, -1, -1},
            {  1   , -1,  1},
            { -1   , -1, -1},
            { -0.33, -1,  1},
            { -0.33,  1, -1},
            { -1   ,  1,  1},
            {  1   ,  1, -1},
            {  0.33,  1,  1}
        };
        setupMultiRotorMixer(mixer);
        m_aircraft->mrStatusLabel->setText("Configuration OK");

    } else if (m_aircraft->multirotorFrameType->itemData(m_aircraft->multirotorFrameType->currentIndex()) == SystemSettings::AIRFRAMETYPE_OCTOCOAXP) {
        airframeType = SystemSettings::AIRFRAMETYPE_OCTOCOAXP;

        //Show any config errors in GUI
        if (throwConfigError(8)) {
            return airframeType;
        }
        motorList << "VTOLMotorN" << "VTOLMotorNE" << "VTOLMotorE" << "VTOLMotorSE"
                  << "VTOLMotorS" << "VTOLMotorSW" << "VTOLMotorW" << "VTOLMotorNW";
        setupMotors(motorList);
        // Motor 1 to 8:
        //     pitch   roll    yaw
        double mixer [8][3] = {
            {  1,  0, -1},
            {  1,  0,  1},
            {  0, -1, -1},
            {  0, -1,  1},
            { -1,  0, -1},
            { -1,  0,  1},
            {  0,  1, -1},
            {  0,  1,  1}
        };
        setupMultiRotorMixer(mixer);
        m_aircraft->mrStatusLabel->setText("Configuration OK");

    } else if (m_aircraft->multirotorFrameType->itemData(m_aircraft->multirotorFrameType->currentIndex()) == SystemSettings::AIRFRAMETYPE_OCTOCOAXX) {
        airframeType = SystemSettings::AIRFRAMETYPE_OCTOCOAXX;

        //Show any config errors in GUI
        if (throwConfigError(8)) {
            return airframeType;
        }
        motorList << "VTOLMotorNW" << "VTOLMotorN" << "VTOLMotorNE" << "VTOLMotorE"
                  << "VTOLMotorSE" << "VTOLMotorS" << "VTOLMotorSW" << "VTOLMotorW";
        setupMotors(motorList);
        // Motor 1 to 8:
        //     pitch   roll    yaw
        double mixer [8][3] = {
            {  1,  1, -1},
            {  1,  1,  1},
            {  1, -1, -1},
            {  1, -1,  1},
            { -1, -1, -1},
            { -1, -1,  1},
            { -1,  1, -1},
            { -1,  1,  1}
        };
        setupMultiRotorMixer(mixer);
        m_aircraft->mrStatusLabel->setText("Configuration OK");

    } else if (m_aircraft->multirotorFrameType->itemData(m_aircraft->multirotorFrameType->currentIndex()) == SystemSettings::AIRFRAMETYPE_TRI) {
        airframeType = SystemSettings::AIRFRAMETYPE_TRI;

        //Show any config errors in GUI
        if (throwConfigError(3)) {
            return airframeType;

        }
        if (m_aircraft->triYawChannelBox->currentText() == "None") {
            m_aircraft->mrStatusLabel->setText("<font color='red'>Error: Assign a Yaw channel</font>");
            return airframeType;
        }
        motorList << "VTOLMotorNW" << "VTOLMotorNE" << "VTOLMotorS";
        setupMotors(motorList);

        GUIConfigDataUnion config = GetConfigData();
        config.multi.TRIYaw = m_aircraft->triYawChannelBox->currentIndex();
        SetConfigData(config);


        // Motor 1 to 6, Y6 Layout:
        //     pitch   roll    yaw
        double mixer [8][3] = {
            {  0.5,  1,  0},
            {  0.5, -1,  0},
            { -1,  0,  0},
            {  0,  0,  0},
            {  0,  0,  0},
            {  0,  0,  0},
            {  0,  0,  0},
            {  0,  0,  0}
        };
        setupMultiRotorMixer(mixer);

        //tell the mixer about tricopter yaw channel

        int channel = m_aircraft->triYawChannelBox->currentIndex()-1;
        if (channel > -1) {
            setMixerType(mixerSettings, channel, MixerSettings::MIXER1TYPE_SERVO);
            setMixerVectorValue(mixerSettings, channel, MixerSettings::MIXER1VECTOR_YAW, 127);
        }

        m_aircraft->mrStatusLabel->setText(tr("Configuration OK"));

    }

    return airframeType;
}