/*
 * This overridden function updates UAVObjects which have no direct relation
 * to any of widgets. Aftewards it calls base class function to take care of
 * other object to widget relations which were dynamically added.
 */
void ConfigCameraStabilizationWidget::updateObjectsFromWidgets()
{
    // Save state of the module enable checkbox first.
    // Do not use setData() member on whole object, if possible, since it triggers
    // unnessesary UAVObect update.
    quint8 enableModule    = ui->enableCameraStabilization->isChecked() ?
                             HwSettings::OPTIONALMODULES_ENABLED : HwSettings::OPTIONALMODULES_DISABLED;
    HwSettings *hwSettings = HwSettings::GetInstance(getObjectManager());

    hwSettings->setOptionalModules(HwSettings::OPTIONALMODULES_CAMERASTAB, enableModule);

    // Update mixer channels which were mapped to camera outputs in case they are
    // not used for other function yet
    MixerSettings *mixerSettings = MixerSettings::GetInstance(getObjectManager());
    MixerSettings::DataFields mixerSettingsData = mixerSettings->getData();

    // TODO: Need to reformat object so types are an
    // array themselves.  This gets really awkward
    quint8 *mixerTypes[] = {
        &mixerSettingsData.Mixer1Type,
        &mixerSettingsData.Mixer2Type,
        &mixerSettingsData.Mixer3Type,
        &mixerSettingsData.Mixer4Type,
        &mixerSettingsData.Mixer5Type,
        &mixerSettingsData.Mixer6Type,
        &mixerSettingsData.Mixer7Type,
        &mixerSettingsData.Mixer8Type,
        &mixerSettingsData.Mixer9Type,
        &mixerSettingsData.Mixer10Type,
    };
    const int NUM_MIXERS = sizeof(mixerTypes) / sizeof(mixerTypes[0]);

    QComboBox *outputs[] = {
        ui->rollChannel,
        ui->pitchChannel,
        ui->yawChannel
    };
    const int NUM_OUTPUTS = sizeof(outputs) / sizeof(outputs[0]);

    ui->message->setText("");
    bool widgetUpdated;
    do {
        widgetUpdated = false;

        for (int i = 0; i < NUM_OUTPUTS; i++) {
            // Channel 1 is second entry, so becomes zero
            int mixerNum = outputs[i]->currentIndex() - 1;

            if ((mixerNum >= 0) && // Short circuit in case of none
                (*mixerTypes[mixerNum] != MixerSettings::MIXER1TYPE_DISABLED) &&
                (*mixerTypes[mixerNum] != MixerSettings::MIXER1TYPE_CAMERAROLLORSERVO1 + i)) {
                // If the mixer channel already mapped to something, it should not be
                // used for camera output, we reset it to none
                outputs[i]->setCurrentIndex(0);
                ui->message->setText("One of the channels is already assigned, reverted to none");

                // Loop again or we may have inconsistent widget and UAVObject
                widgetUpdated = true;
            } else {
                // Make sure no other channels have this output set
                for (int j = 0; j < NUM_MIXERS; j++) {
                    if (*mixerTypes[j] == (MixerSettings::MIXER1TYPE_CAMERAROLLORSERVO1 + i)) {
                        *mixerTypes[j] = MixerSettings::MIXER1TYPE_DISABLED;
                    }
                }

                // If this channel is assigned to one of the outputs that is not disabled
                // set it
                if ((mixerNum >= 0) && (mixerNum < NUM_MIXERS)) {
                    *mixerTypes[mixerNum] = MixerSettings::MIXER1TYPE_CAMERAROLLORSERVO1 + i;
                }
            }
        }
    } while (widgetUpdated);

    // FIXME: Should not use setData() to prevent double updates.
    // It should be refactored after the reformatting of MixerSettings UAVObject.
    mixerSettings->setData(mixerSettingsData);

    ConfigTaskWidget::updateObjectsFromWidgets();
}