function guifi_device_save($edit, $verbose = TRUE, $notify = TRUE)
{
    global $user;
    global $bridge;
    guifi_log(GUIFILOG_TRACE, 'function guifi_device_save()', $edit);
    $bridge = FALSE;
    $to_mail = array();
    $tomail[] = $user->mail;
    $log = "";
    $to_mail = array();
    // device
    // TODO : corretgir que agafi els midi fid de l'estructura qeu toca dins del edit
    // amb lo de sota els repliquem per poder-hi accedir directament
    if (in_array($edit['type'], array('radio', 'switch'))) {
        $edit['mid'] = $edit['variable']['model_id'];
        $edit['fid'] = $edit['variable']['firmware_id'];
    }
    if ($edit['type'] == 'radio') {
        if (!$edit['variable']['firmware']) {
            $firmware = db_fetch_object(db_query("SELECT id, nom as name " . "FROM {guifi_firmware} " . "WHERE id = '%d'", $edit['fid']));
            $edit['variable']['firmware'] = $firmware->name;
        }
    }
    // TODO REMOVE EXTRA  comprovar que no es serialitzen els camps de mid, fid, etc.
    if (!empty($edit['variable'])) {
        $edit['extra'] = serialize($edit['variable']);
    }
    // busquem el id de la configuracioUSC per aquests mid i fid
    $sql = db_query('SELECT id as uscid, enabled FROM {guifi_configuracioUnSolclic} WHERE mid=%d and fid=%d ', $edit['mid'], $edit['fid']);
    $configuracio = db_fetch_object($sql);
    $edit['usc_id'] = $configuracio->uscid;
    $ndevice = _guifi_db_sql('guifi_devices', array('id' => $edit['id']), $edit, $log, $to_mail);
    guifi_maintainers_save($ndevice['id'], 'device', $edit['maintainers']);
    guifi_funders_save($ndevice['id'], 'device', $edit['funders']);
    // Ensure we have all ports filled up to etherdev_max/optodev_max at model_specs
    $m = guifi_get_model_specs($edit['mid']);
    guifi_log(GUIFILOG_TRACE, 'function guifi_device_save(m)', $m);
    $interfaces = array_values($edit['interfaces']);
    guifi_log(GUIFILOG_TRACE, sprintf('switch %d saved, %d ports:', $ndevice['id'], $m->etherdev_max), $edit);
    if ($m->ethermax) {
        for ($port = 1; $port <= $m->ethermax; $port++) {
            if (!isset($interfaces[$port - 1])) {
                $ninterface = array('new' => true, 'interface_type' => isset($m->ethernames[$port - 1]) ? $m->ethernames[$port - 1] : $port, 'etherdev_counter' => $port, 'interface_class' => 'ethernet', 'device_id' => $ndevice['id'], 'mac' => _guifi_mac_sum($edit['mac'], $port - 1));
                guifi_log(GUIFILOG_TRACE, sprintf('inserting interface at %d:', $ndevice['id']), $ninterface);
                _guifi_db_sql('guifi_interfaces', null, $ninterface, $log, $to_mail);
            }
        }
    }
    guifi_log(GUIFILOG_TRACE, sprintf('device saved:'), $ndevice);
    $movenode = explode('-', $edit['movenode']);
    // radios
    $rc = 0;
    if (is_array($edit['radios'])) {
        ksort($edit['radios']);
    }
    $rc = 0;
    if ($edit['radios']) {
        foreach ($edit['radios'] as $radiodev_counter => $radio) {
            $keys['id'] = $ndevice['id'];
            $keys['radiodev_counter'] = $radiodev_counter;
            $radio['id'] = $ndevice['id'];
            $radio['radiodev_counter'] = $rc;
            if ($movenode[0]) {
                $radio['nid'] = $movenode[0];
            }
            $radio['model_id'] = $edit['variable']['model_id'];
            // check if device id has changed
            guifi_log(GUIFILOG_TRACE, sprintf('Checking radio (from:%d, to: %d): ', $radio['id'], $radio['to_id']), NULL);
            if (isset($radio['to_did'])) {
                // if radio has moved to another device:
                // -obtain the radiodev_counter of that device
                // -if has wLan/Lan interface:
                //   -convert to wlan
                //   -don't save it again at cable interfaces section'
                if ($radio['to_did'] != $radio['id']) {
                    $radiomoved = TRUE;
                    // -obtain the radiodev_counter of that device
                    $radio['id'] = $radio['to_did'];
                    $qry = db_query('SELECT max(radiodev_counter) + 1 rc ' . 'FROM {guifi_radios} ' . 'WHERE id=%d', $radio['to_did']);
                    $nrc = db_fetch_array($qry);
                    if (empty($nrc['rc'])) {
                        $nrc['rc'] = '0';
                    }
                    $radio['radiodev_counter'] = $nrc['rc'];
                    drupal_set_message(t('Radio# %id has been moved to radio# %id2 at device %dname', array('%id' => $rc, '%id2' => $radio['radiodev_counter'], '%dname' => guifi_get_hostname($radio['to_did']))));
                    // -if has wLan/Lan interface:
                    //   -convert to wlan if is not going a be the main radio
                    //   -don't save it again at cable interfaces section'
                    if ($radio['interfaces']) {
                        foreach ($radio['interfaces'] as $iid => $interface) {
                            if ($interface['interface_type'] == 'wLan/Lan') {
                                foreach ($edit['interfaces'] as $ciid => $cinterface) {
                                    // unset from cable section
                                    if ($cinterface['interface_type'] == 'wLan/Lan') {
                                        unset($edit['interfaces'][$ciid]);
                                    }
                                }
                                // if not radio#0, set as wLan at the other device
                                if ($nrc['rc']) {
                                    $radio['interfaces'][$iid]['interface_type'] = 'wLan';
                                }
                            }
                        }
                    }
                    $radio['interfaces'][$iid]['related_interfaces'] = $radio['to_did'] . ',' . $nrc['rc'];
                }
            }
            // save the radio
            $nradio = _guifi_db_sql('guifi_radios', $keys, $radio, $log, $to_mail);
            if (empty($nradio) or $radio['deleted']) {
                continue;
            }
            // interfaces
            if ($radio['interfaces']) {
                foreach ($radio['interfaces'] as $interface_id => $interface) {
                    $interface['device_id'] = $radio['id'];
                    $interface['mac'] = $radio['mac'];
                    $interface['radiodev_counter'] = $nradio['radiodev_counter'];
                    $log .= guifi_device_interface_save($interface, $interface_id, $edit['id'], $ndevice['nid'], $to_mail);
                }
            }
            // foreach interface
            $rc++;
        }
    }
    // foreach radio
    // Interfaces
    if (!empty($edit['interfaces'])) {
        // Set etherdev_counter (sort the interfaces by it)
        uasort($edit['interfaces'], 'guifi_interfaces_cmp');
        guifi_log(GUIFILOG_TRACE, 'Saving interfaces, interface:', $edit['interfaces']);
        $m = guifi_get_model_specs($edit['variable']['model_id']);
        $iCount = 0;
        // Save the interface
        foreach ($edit['interfaces'] as $iid => $interface) {
            $interface['device_id'] = $ndevice['id'];
            $interface['etherdev_counter'] = $iCount;
            if (in_array($edit['type'], array('switch'))) {
                $interface[interface_type] = $m->ethernames[$iCount];
            }
            $interface[interface_class] = 'ethernet';
            $iCount++;
            guifi_log(GUIFILOG_TRACE, sprintf('iid: %d, edit[nid]: %d, ndevice[id]: %d, interface:', $iid, $edit['nid'], $ndevice['nid'], $ndevice['nid']), $interface);
            if ($iid != 'ifs') {
                $log .= guifi_device_interface_save($interface, $iid, $edit['id'], $ndevice['nid'], $to_mail);
            }
        }
    }
    // vlans & aggregations
    foreach (array('vlans', 'aggregations') as $iClass) {
        if (!empty($edit[$iClass])) {
            // Save the interface
            foreach ($edit[$iClass] as $iid => $interface) {
                if ($radiomoved == TRUE) {
                    if ($interface['interface_class'] == 'wds/p2p') {
                        continue;
                    }
                }
                if (is_array($interface[related_interfaces])) {
                    $interface[related_interfaces] = implode('|', $interface[related_interfaces]);
                }
                $interface['device_id'] = $ndevice['id'];
                $log .= guifi_device_interface_save($interface, $iid, $edit['id'], $ndevice['nid'], $to_mail);
            }
        }
    }
    // ipv4s
    if (!empty($edit[ipv4])) {
        guifi_log(GUIFILOG_TRACE, 'guifi_device_save (ipv4s)', $edit['ipv4']);
        foreach ($edit['ipv4'] as $k => $ipv4) {
            if (is_numeric($k)) {
                guifi_log(GUIFILOG_TRACE, 'guifi_device_save (ipv4)', $ipv4);
                $iipv4 = db_fetch_array(db_query("SELECT * FROM {guifi_ipv4} WHERE ipv4 = '%s' ", $ipv4['ipv4']));
                $countqry = db_query("SELECT COUNT(*) FROM {guifi_ipv4} WHERE interface_id = %d", $iipv4['interface_id']);
                $count = db_result($countqry, 0);
                $ipv4_id = $count + 1;
                // TODO abans del save cal comprovar un id ipv4 disponbile, modificar-lo als links si en te, si es un link sense fils no ha de permtre triar uan interficie etherX,etc..
                //   db_query("UPDATE {guifi_ipv4} SET id = %d, interface_id = %d WHERE ipv4 = '%s' AND interface_id = %d",$ipv4_id, $ipv4['interface_id'],$iipv4['ipv4'],$iipv4['interface_id']);
            }
        }
    }
    $to_mail = explode(',', $edit['notification']);
    if ($edit['new']) {
        $subject = t('The device %name has been CREATED by %user.', array('%name' => $edit['nick'], '%user' => $user->name));
    } else {
        $subject = t('The device %name has been UPDATED by %user.', array('%name' => $edit['nick'], '%user' => $user->name));
    }
    //   drupal_set_message($subject);
    guifi_notify($to_mail, $subject, $log, $verbose, $notify);
    guifi_node_set_flag($edit['nid']);
    guifi_clear_cache($edit['nid']);
    guifi_clear_cache($edit['id']);
    variable_set('guifi_refresh_dns', time());
    return $ndevice['id'];
}
/**
 * @param array containing editing device information  $edit
 * @param weight form ewlements $form_weight
 */
function guifi_ports_form($edit, &$form_weight)
{
    global $user;
    guifi_log(GUIFILOG_TRACE, 'function guifi_ports_form()', $edit);
    // Select device model from model_specs
    if (!empty($edit['mid'])) {
        $querymid = db_query("\n      SELECT mid, model, etherdev_max, optoports_max, m.opto_interfaces, f.name manufacturer\n      FROM guifi_model_specs m, guifi_manufacturer f\n      WHERE f.fid = m.fid\n      AND m.mid = " . $edit['mid']);
        $swmodel = db_fetch_object($querymid);
    }
    switch ($edit['type']) {
        case 'switch':
            $fs_title = t('Switch ports & connections');
            $swtype = true;
            break;
        default:
            $fs_title = t('Physical ports & connections');
            $swtype = false;
    }
    // Build port fieldset
    $form = array('#type' => 'fieldset', '#title' => t('Ports'), '#collapsible' => TRUE, '#tree' => TRUE, '#collapsed' => FALSE, '#weight' => $form_weight++, '#prefix' => '<br><img src="/' . drupal_get_path('module', 'guifi') . '/icons/ports-16.png"> ' . t('%title section', array('%title' => $fs_title)));
    guifi_log(GUIFILOG_TRACE, 'function guifi_ports_form()', $swmodel);
    $opto_interfaces = explode('|', $swmodel->opto_interfaces);
    guifi_log(GUIFILOG_TRACE, 'function guifi_ports_form(opto_interfaces)', $opto_interfaces);
    // if no switch model selected / unknown number of ports, ask for save
    if (empty($swmodel->etherdev_max) and empty($edit['mid'])) {
        $form['msg'] = array('#type' => 'item', '#value' => t('Number of ports is still unknown. Select a model above and save & continue edit to populate ports.'), '#weight' => $form_weight++);
    }
    $connector_types = array('RJ45' => str_pad(t('RJ45 Cooper'), $type_length, '-'));
    if ($swmodel->opto_interfaces) {
        $connector_types = array_merge($connector_types, guifi_types('fo_port'));
    }
    // Loop across all existing interfaces
    $port_count = 0;
    $total_ports = count($edit['interfaces']);
    $first_port = true;
    $eCountOpts = array();
    for ($i = 0; $i < $total_ports; $i++) {
        $eCountOpts[$i] = $i;
    }
    $m = guifi_get_model_specs($edit[variable][model_id]);
    guifi_log(GUIFILOG_TRACE, 'function guifi_ports_form(m)', $m);
    foreach ($edit['interfaces'] as $port => $interface) {
        guifi_log(GUIFILOG_TRACE, 'function guifi_ports_form(interface)', $interface);
        // Skip ports:
        // -with no interface type
        // -with related interfaces
        // -no interface_class but 'wLan/Lan' (v1 schema)
        if (empty($interface['interface_type']) or !empty($interface[related_interfaces]) or empty($interface[interface_class]) and $interface[interface_type] == 'wLan/Lan') {
            guifi_log(GUIFILOG_TRACE, 'function guifi_ports_form(interface)', $interface);
            continue;
        }
        $prefix = '';
        $suffix = '';
        $port_count++;
        $form[$port] = array('#type' => 'fieldset', '#attributes' => array('class' => 'fieldset-interface-port'), '#prefix' => '<div id="fieldset-port-' . $port . '">', '#suffix' => '</div>', '#tree' => TRUE);
        $form[$port]['etherdev_counter'] = array('#tree' => TRUE, '#type' => 'select', '#title' => $first_port ? t('#') : false, '#options' => $eCountOpts, '#default_value' => $port_count - 1, '#attributes' => array('class' => 'interface-item'), '#weight' => $form_weight++);
        $form[$port]['interface_type'] = array('#tree' => TRUE, '#type' => 'textfield', '#title' => $first_port ? t('name') : false, '#default_value' => $interface['deleted'] ? t('deleted') . ' - ' . $interface['interface_type'] : $interface['interface_type'], '#size' => in_array($edit['type'], array('switch')) ? 10 : 20, '#size' => 10, '#maxlength' => 40, '#disabled' => $interface['deleted'] or in_array($edit['type'], array('switch')) ? TRUE : FALSE, '#attributes' => array('class' => 'interface-item'), '#weight' => $form_weight++);
        if ($form[$port]['interface_type']['#disabled'] == true) {
            $form[$port]['interface_type']['#value'] = $interface['interface_type'];
            $form[$port]['interface_type']['#attributes'] = array('class' => 'interface-item-disabled');
            if (empty($interface['deleted'])) {
                $form[$port]['iname'] = array('#tree' => true, '#type' => 'hidden', '#value' => $interface['interface_type']);
            }
        }
        guifi_log(GUIFILOG_TRACE, 'function guifi_ports_form(type)', $interface);
        $form[$port]['connector_type'] = array('#tree' => TRUE, '#type' => 'select', '#title' => $first_port ? t('connector') : false, '#options' => $connector_types, '#disabled' => in_array($interface['interface_type'], $opto_interfaces) ? false : true, '#default_value' => $interface['connector_type'], '#attributes' => in_array($interface['interface_type'], $opto_interfaces) ? array('class' => 'interface-item') : array('class' => 'interface-item-disabled'), '#weight' => $form_weight++);
        if (!empty($interface['connto_did'])) {
            $dname = guifi_get_devicename($interface['connto_did']);
            $dinterfaces = guifi_get_device_interfaces($interface['connto_did'], $interface['connto_iid']);
        } else {
            $dname = '';
        }
        $form[$port]['dname'] = array('#type' => 'textfield', '#tree' => TRUE, '#title' => $first_port ? t('connects to') : false, '#disabled' => true, '#size' => 30, '#maxsize' => 256, '#value' => $interface['connto_iid'] ? $dname . ' / ' . $dinterfaces[$interface['connto_iid']] : $dname, '#attributes' => empty($dname) ? array('class' => 'interface-item-available') : array('class' => 'interface-item-disabled'), '#weight' => $form_weight++);
        if (!$interface[deleted]) {
            $form[$port]['addLink'] = array('#type' => 'image_button', '#src' => $interface['deleted'] ? drupal_get_path('module', 'guifi') . '/icons/drop.png' : drupal_get_path('module', 'guifi') . '/icons/edit.png', '#attributes' => array('title' => t('Edit dialog for connecting to another device'), 'class' => 'interface-item.form-button'), '#ahah' => array('path' => 'guifi/js/edit_cableconn/' . $port, 'wrapper' => 'interface-cableconn-' . $port, 'method' => 'replace', 'effect' => 'fade'), '#prefix' => $first_port ? '<div class="form-item"><div>&nbsp</div>' : '<div class="form-item">', '#suffix' => '</div>', '#weight' => $form_weight++);
            /* If onclick is wanted to edit, uncomment this
               $form[$port]['dname']['#disabled'] = false;
               $form[$port]['dname']['#ahah'] = array(
                   'event' => 'mousedown',
                   'path' => 'guifi/js/edit_cableconn/'.$port,
                   'wrapper' => 'interface-cableconn-'.$port,
                   'method' => 'replace',
                   'effect' => 'fade',
               );
               */
        }
        $form[$port]['vlan'] = array('#tree' => TRUE, '#type' => 'textfield', '#type' => in_array($edit['type'], array('switch')) ? 'hidden' : 'textfield', '#type' => 'hidden', '#title' => $first_port ? t('vlan') : false, '#size' => 6, '#maxlength' => 10, '#default_value' => $interface['vlan'], '#attributes' => array('class' => 'interface-item'), '#weight' => $form_weight++);
        $form[$port]['comments'] = array('#tree' => TRUE, '#type' => 'textfield', '#title' => $first_port ? t('comments') : false, '#size' => 40, '#maxlength' => 60, '#default_value' => $interface['comments'], '#attributes' => array('class' => 'interface-item'), '#weight' => $form_weight++);
        if ($interface[deleted]) {
            $form[$port]['comments']['#value'] = t('will be deleted. press "reset" to cancel');
            $form[$port]['comments']['#disabled'] = true;
        }
        if (!$interface[deleted]) {
            $form[$port]['mac'] = array('#type' => 'textfield', '#title' => $first_port ? t('mac') : false, '#required' => FALSE, '#size' => 20, '#maxlength' => 17, '#default_value' => $interface['mac'], '#element_validate' => array('guifi_mac_validate'), '#weight' => $form_weight++);
        }
        if (!$interface[deleted] and !($port_count <= $m->ethermax)) {
            $form[$port]['delete'] = array('#type' => 'image_button', '#title' => $first_port ? t('delete') : false, '#src' => drupal_get_path('module', 'guifi') . '/icons/drop.png', '#attributes' => array('title' => t('Delete interface' . $m->ethermax . '-' . $port_count)), '#submit' => array('guifi_vinterfaces_delete_submit'), '#prefix' => $first_port ? '<div class="form-item"><label>&nbsp</label>' : false, '#suffix' => $first_port ? '</div>' : false);
        }
        $form[$port]['conn'] = array('#type' => 'hidden', '#prefix' => '<div id="interface-cableconn-' . $port . '">', '#suffix' => '</div>', '#weight' => $form_weight++);
        $form[$port]['conn']['did'] = array('#type' => 'textfield', '#parents' => array('interfaces', $port, 'did'), '#value' => guifi_get_devicename($interface['connto_did'], 'large'), '#autocomplete_path' => 'guifi/js/select-node-device', '#size' => 60, '#maxlength' => 128, '#element_validate' => array('guifi_devicename_validate'), '#attributes' => array('class' => 'interface-item'), '#ahah' => array('path' => 'guifi/js/select-device-interface/' . $port, 'wrapper' => 'fieldset-port-' . $port, 'method' => 'replace', 'effect' => 'fade'));
        $form[$port]['conn']['if'] = array('#parents' => array('interfaces', $port, 'if'), '#type' => 'select', '#value' => $interface['connto_iid'], '#attributes' => array('class' => 'interface-item'), '#options' => $dinterfaces, '#ahah' => array('path' => 'guifi/js/select-device-interface/' . $port, 'wrapper' => 'fieldset-port-' . $port, 'method' => 'replace', 'effect' => 'fade'));
        // Hidden fields
        $form[$port]['id'] = array('#type' => 'hidden', '#value' => $interface['id'], '#weight' => $form_weight++);
        $form[$port]['device_id'] = array('#type' => 'hidden', '#value' => $interface['device_id'], '#weight' => $form_weight++);
        $form[$port]['connto_did'] = array('#type' => 'hidden', '#value' => $interface['connto_did'], '#weight' => $form_weight++);
        $form[$port]['connto_iid'] = array('#type' => 'hidden', '#value' => $interface['connto_iid'], '#weight' => $form_weight++);
        if ($interface['deleted']) {
            $form[$port]['deleted'] = array('#type' => 'hidden', '#value' => $interface['deleted'], '#weight' => $form_weight++);
        }
        if ($interface['new']) {
            $form[$port]['new'] = array('#type' => 'hidden', '#value' => $interface['new'], '#weight' => $form_weight++);
        }
        $first_port = false;
    }
    return $form;
}