<?php
/**
 *
 * @package    mahara
 * @subpackage form-element
 * @author     Catalyst IT Limited <mahara@catalyst.net.nz>
 * @license    https://www.gnu.org/licenses/gpl-3.0.html GNU GPL version 3 or later
 * @copyright  For copyright information on Mahara, please see the README file distributed with this software.
 *
 */

/**
 * Provides a control that allows the user to input where in a list they want
 * to put something. Handy for indicating the order of some objects.
 *
 * @param Pieform  $form    The form to render the element for
 * @param array    $element The element to render
 * @return string           The HTML for the element
 */
function pieform_element_weight(Pieform $form, $element) {
    pieform_element_weight_validate_element($element);

    $default = (isset($element['defaultvalue'])) ? intval($element['defaultvalue']) : 0;
    $result = '<input type="radio"'. $form->element_attributes($element) . ' value="0"';
    if ($default == 0) {
        $result .= ' checked="checked"';
    }
    $result .= '>';

    $i = 0;
    foreach ($element['existing'] as $existing) {
        $i++;
        $result .= "<br>" . Pieform::hsc($existing['title']);
        $result .= "<br><input type=\"radio\"" . $form->element_attributes($element) . " value=\"$i\"";
        if ($i == $default) {
            $result .= ' checked="checked"';
        }
        $result .= '>';
    }

    return $result;

    return '<input type="text"'
        . $form->element_attributes($element)
        . ' value="' . Pieform::hsc($form->get_value($element)) . '">';
}

function pieform_element_weight_set_attributes($element) {
    $element['returnpolicy'] = 'renumber-from-zero';
    return $element;
}

function pieform_element_weight_get_value(Pieform $form, $element) {
    pieform_element_weight_validate_element($element);
    $name = $element['name'];

    $global = ($form->get_property('method') == 'get') ? $_GET : $_POST;

    $value = null;
    if (isset($element['value'])) {
        $value = $element['value'];
    }
    else if (isset($global[$name])) {
        $value = $global[$name];
    }
    else if (isset($element['defaultvalue'])) {
        $value = $element['defaultvalue'];
    }

    // How should we return the value? In theory, there could be several ways
    // in which the caller wants the data to be returned. For now, only one
    // "policy" is implemented
    switch ($element['returnpolicy']) {
    case 'renumber-from-zero':
        return pieform_element_weight_returnpolicy_renumber_from_zero($element, $value);
    }

    return null;
}

function pieform_element_weight_validate_element($element) {
    if (!isset($element['existing'])) {
        throw new PieformException('weight element requires "existing" data');
    }

    if (!is_array($element['existing'])) {
        throw new PieformException('"existing" data should be an array of hashes, each with keys "id", "weight" and "title"');
    }

    foreach ($element['existing'] as $existing) {
        if (!array_key_exists('id', $existing) || !array_key_exists('weight', $existing) || !array_key_exists('title', $existing)) {
            throw new PieformException('Elements of the "existing" data should have "id", "weight" and "title" keys');
        }
    }
}

/**
 * Returns an array of weight => id pairs.
 *
 * The new element has an id of 'null'
 */
function pieform_element_weight_returnpolicy_renumber_from_zero($element, $value) {
    $element['existing'] = pieform_element_weight_renumber_existing_from_zero($element['existing']);
    $element['existing'][] = array('weight' => $value - 0.5, 'id' => null);
    usort($element['existing'], function($a, $b) { return $a["weight"] > $b["weight"]; });

    $return = array();
    foreach ($element['existing'] as $existing) {
        $return[] = $existing['id'];
    }
    return $return;
}

function pieform_element_weight_renumber_existing_from_zero($existing) {
    usort($existing, function($a, $b) { return $a["weight"] > $b["weight"]; });

    $i = 0;
    foreach ($existing as &$item) {
        $item['weight'] = $i++;
    }
    return $existing;
}
