$response = '';
switch ($action) {
    case 'bookmark_added':
        $response = insert_bookmark($data);
        if ($response == 'Success') {
            $response = get_recommendations_for_bookmarked_document($data);
        }
        break;
    case 'bookmark_deleted':
        $response = delete_bookmark($data);
        break;
    case 'keywords_changed':
        $response = get_recommendations_for_keywords($data);
        break;
    case 'initial_data_added':
        $response = insert_bookmark($data);
        break;
    default:
        return_error('Unknown action', '1002');
        break;
}
echo $response;
function insert_bookmark($parameters)
{
    $expected_parameters = array('user_id', 'document_id', 'document_title', 'query', 'keywords');
    validate_all_parameters_set($parameters, $expected_parameters);
    // if false returns echoes error message back
    $qk_string = get_qk_string($parameters['query'], $parameters['keywords']);
    $mysqli = get_mysqli();
    set_sp_parameter($mysqli, '@user_id', $parameters['user_id']);
    set_sp_parameter($mysqli, '@document_id', $parameters['document_id']);
function mode_entry_insertion()
{
    global $session_data;
    global $import_id;
    $tag_map = array();
    if (@$_REQUEST['orig_tags']) {
        $orig_tags = $_REQUEST['orig_tags'];
        $tags = $_REQUEST['tags'];
        if (count($orig_tags) == count($tags)) {
            for ($i = 0; $i < count($tags); ++$i) {
                $tag_map[strtolower($orig_tags[$i])] = $tags[$i];
            }
        }
    }
    $tags_for_all = explode(',', @$_REQUEST['tags_for_all']);
    $workgroup_tag_id = intval(@$_REQUEST["workgroup_tag"]);
    $session_data['import_time'] = date('Y-m-d H:i:s');
    // add a tag (tag) for this import session to all entries
    $import_tag = 'File Import ' . $session_data['import_time'];
    $res = mysql__insert('usrTags', array('tag_Text' => $import_tag, 'tag_UGrpID' => get_user_id()));
    // add a saved search for records with this tag
    $now = date('Y-m-d');
    mysql__insert('usrSavedSearches', array('svs_Name' => $import_tag, 'ss_url' => '?ver=1&w=all&q=kwd%3A%22' . str_replace(' ', '%20', $import_tag) . '%22', 'svs_UGrpID' => get_user_id(), 'svs_Added' => $now, 'svs_Modified' => $now));
    set_progress_bar_title('Preparing database entries');
    $creatorDT = defined('DT_CREATOR') ? DT_CREATOR : 0;
    $j = 0;
    foreach (array_keys($session_data['out_entries']) as $i) {
        $entry =& $session_data['out_entries'][$i];
        $entry->addTag($import_tag);
        // add general import kwd
        if ($tags_for_all) {
            foreach ($tags_for_all as $tag) {
                if (trim($tag)) {
                    $entry->addTag(trim($tag), true);
                }
            }
        }
        if ($workgroup_tag_id) {
            $entry->setWorkgroupTag($workgroup_tag_id);
        }
        $_entry =& $entry;
        do {
            // for each container set up the author records
            $fields = $_entry->getFields();
            foreach (array_keys($fields) as $i) {
                if (!$fields[$i]->getValue()) {
                    continue;
                }
                if ($fields[$i]->getType() == $creatorDT) {
                    //MAGIC NUMBER 158
                    // an author: cook the value -- could be several authors
                    process_author($fields[$i]);
                    foreach ($fields[$i]->getValue() as $person_bib_id) {
                        $_entry->addAuthor($person_bib_id);
                    }
                }
            }
            unset($fields);
            $_entry =& $_entry->_container;
        } while ($_entry);
        unset($_entry);
        unset($entry);
        update_progress_bar(++$j / count($session_data['out_entries']));
    }
    update_progress_bar(-1);
    process_disambiguations();
    $session_data['ambiguities'] = array();
    $ambig_count = 0;
    $j = 0;
    $out_entry_count = count($session_data['out_entries']);
    global $zoteroItems;
    $zoteroItems = array();
    list($usec, $sec) = explode(' ', microtime());
    $stime = $sec + $usec;
    set_progress_bar_title('Checking against existing entries');
    foreach (array_keys($session_data['out_entries']) as $i) {
        unset($entry);
        $entry =& $session_data['out_entries'][$i];
        if ($entry->getBookmarkID()) {
            ++$session_data['dupe-records-count'];
            ++$session_data['dupe-bookmark-count'];
            unset($session_data['out_entries'][$i]);
            // in the future we should unset these from the session data
            continue;
            // already inserted;
        }
        //		if (! $entry->getBiblioID())
        //			insert_biblio($entry);	// insert a (temporary) records entry
        //		$temp_bib_id = $entry->getBiblioID();
        if (!find_exact_entry($entry)) {
            find_similar_entries($entry);
        }
        if ($entry->getBiblioID() && $entry->_permanent) {
            //set in find_exact_entry
            // already in the database
            // copy across any new data
            // FIXME			merge_biblio($entry->getBiblioID(), $temp_bib_id);
            // find any data that is not already part of the entry, and merge it in
            merge_new_biblio_data($entry->getBiblioID(), $entry);
            // Make sure there's a bookmark
            @++$session_data['dupe-records-count'];
            if (!@$session_data['dupe-biblios']) {
                $session_data['dupe-biblios'] = array();
            }
            array_push($session_data['dupe-biblios'], $entry->getBiblioID());
            if (insert_bookmark($entry)) {
                @++$session_data['added-bookmark-count'];
            } else {
                @++$session_data['dupe-bookmark-count'];
            }
            insert_tags($entry, $tag_map);
            delete_biblio($entry);
            unset($session_data['out_entries'][$i]);
        } else {
            if ($entry->getPotentialMatches()) {
                // present disambiguation options
                if (!$entry->getBiblioID()) {
                    insert_biblio($entry);
                }
                if (!@$session_data['disambig-biblios']) {
                    $session_data['disambig-biblios'] = array();
                }
                array_push($session_data['disambig-biblios'], $entry->getBiblioID());
                print_disambiguation_options($entry);
                @++$ambig_count;
            } else {
                if ($entry->getAncestor() && $entry->_ancestor->getPotentialMatches()) {
                    // present disambiguation options
                    if (!$entry->getBiblioID()) {
                        insert_biblio($entry);
                    }
                    if (!@$session_data['disambig-ancestor-biblios']) {
                        $session_data['disambig-ancestor-biblios'] = array();
                    }
                    array_push($session_data['disambig-ancestor-biblios'], $entry->getBiblioID());
                    print_disambiguation_options($entry);
                    @++$ambig_count;
                } else {
                    if (!$entry->getAncestor() || $entry->_ancestor->_permanent) {
                        // The entry (and possibly several container entries) needs to be inserted into records
                        $_entry = $entry;
                        do {
                            if (!$_entry->getBiblioID()) {
                                insert_biblio($_entry);
                            }
                            perm_biblio($_entry);
                            $_entry =& $_entry->_container;
                        } while ($_entry && !$_entry->_permanent);
                        if (!@$session_data['added-biblios']) {
                            $session_data['added-biblios'] = array();
                        }
                        array_push($session_data['added-biblios'], $entry->getBiblioID());
                        @++$session_data['added-records-count'];
                        if (insert_bookmark($entry)) {
                            @++$session_data['added-bookmark-count'];
                        } else {
                            @++$session_data['dupe-bookmark-count'];
                        }
                        insert_tags($entry, $tag_map);
                        unset($session_data['out_entries'][$i]);
                    } else {
                        // If we get here then the entry has an ancestor set but no definite/possible records ID for that ancestor.
                        // This goes against the definition of an ancestor, so we shouldn't be here.
                        // This means an internal error, but we may Recover Gracefully.
                        // Insert the entry and all containers.
                        $entry->setAncestor(NULL);
                        perm_biblio($entry);
                        if (!@$session_data['other-biblios']) {
                            $session_data['other-biblios'] = array();
                        }
                        array_push($session_data['other-biblios'], $entry->getBiblioID());
                        ++$session_data['added-records-count'];
                        if (insert_bookmark($entry)) {
                            ++$session_data['added-bookmark-count'];
                        } else {
                            ++$session_data['dupe-bookmark-count'];
                        }
                        insert_tags($entry, $tag_map);
                        unset($session_data['out_entries'][$i]);
                    }
                }
            }
        }
        // FIXME: need to check that entry is inserted properly -- if not, append it to $non_out_entries
        // print "<a target='_other' href='../edit.php?bkmk_id=".$entry->getBookmarkID()."'>".$entry->getBiblioID()."</a><br>";
        // do fancy progress bar stuff
        update_progress_bar(++$j / $out_entry_count);
    }
    update_progress_bar(-1);
    list($usec, $sec) = explode(' ', microtime());
    $etime = $sec + $usec;
    if ($zoteroItems && count($zoteroItems) > 0) {
        ?>
        <div style="display: none;"><xml id="ZoteroItems">
            <?php 
        echo '<?xml version="1.0"?>';
        ?>
                           
            <ZoteroItems>
                <?php 
        foreach ($zoteroItems as $zoteroID => $heuristBibID) {
            ?>
                    <ZoteroItem>
                        <ZoteroID><?php 
            echo $zoteroID;
            ?>
</ZoteroID>
                        <HeuristID><?php 
            echo $heuristBibID;
            ?>
</HeuristID>
                        <HeuristStatus>OK</HeuristStatus>
                        <SyncDate><?php 
            echo time();
            ?>
</SyncDate>
                    </ZoteroItem>
                    <?php 
        }
        ?>
            </ZoteroItems></xml>
        </div>
        <?php 
    }
    if ($ambig_count) {
        ?>
        <hr>
        <br clear=all>
        <input type="submit" value="Continue" style="font-weight: bold;">

        <?php 
    }
    // print summary, print link to non-imported data, print magic "Finished" button
    ?>
    <br clear=all>
    <br clear=all>
    <hr>
    <br clear=all>
    <table cellpadding="5">
        <tr><td><b>Records:</b></td></tr>
        <tr><td>Read:</td><td><?php 
    echo count(@$session_data['in_entries']);
    ?>
</td></tr>
        <tr><td>Added:</td><td><?php 
    echo intval(@$session_data['added-records-count']);
    ?>
</td></tr>
        <tr><td>Dupes:</td><td><?php 
    echo intval(@$session_data['dupe-records-count']);
    ?>
</td></tr>
        <tr><td><b>Bookmarks:</b></td></tr>
        <tr><td>Added:</td><td><?php 
    echo intval(@$session_data['added-bookmark-count']);
    ?>
</td></tr>
        <tr><td>Dupes:</td><td><?php 
    echo intval(@$session_data['dupe-bookmark-count']);
    ?>
</td></tr>
        <tr><td colspan=2>Note: duplicate bookmarks/records and records with errors were not added to the database</td></tr>
        <?php 
    /*
    <tr><td colspan=2>
    <br>added biblios: <a target=_new href="/heurist/?q=ids:<?= join(',', $session_data['added-biblios']) ?>">here</a>
    <br>dupe biblios: <a target=_new href="/heurist/?q=ids:<?= join(',', $session_data['dupe-biblios']) ?>">here</a>
    <br>disambig biblios: <a target=_new href="/heurist/?q=ids:<?= join(',', $session_data['disambig-biblios']) ?>">here</a>
    <br>disambig-ancestor biblios: <a target=_new href="/heurist/?q=ids:<?= join(',', $session_data['disambig-ancestor-biblios']) ?>">here</a>
    <br>other biblios: <a target=_new href="/heurist/?q=ids:<?= join(',', $session_data['other-biblios']) ?>">here</a>
    </td></tr>
    */
    ?>
        <?php 
    if ($ambig_count) {
        ?>
            <tr><td>Possible duplicates waiting for disambiguation:</td><td><?php 
        echo $ambig_count;
        ?>
</td></tr>
            <?php 
    }
    if ($session_data['non_out_entries']) {
        ?>
            <tr><td>Records with data errors:</td><td><?php 
        echo count($session_data['non_out_entries']);
        ?>
</td></tr>
            <?php 
    }
    ?>
    </table>

    <?php 
    if (!@$session_data['zoteroImport']) {
        ?>
        <?php 
        if ($ambig_count || $session_data['non_out_entries']) {
            ?>
            <a target="_errors" href="interface/downloadNonImported.php/<?php 
            echo htmlspecialchars($import_id);
            ?>
-unimported.txt?import_id=<?php 
            echo htmlspecialchars($import_id);
            ?>
" onClick="elt=document.getElementById('finished_button'); if (elt) elt.disabled = false;" style="color: red;">Download non-imported records</a>
            <?php 
        }
        if (!$ambig_count && $session_data['non_out_entries']) {
            ?>
            <input type="button" value="Finished" onClick="window.location.replace('importerFramework.php?db=<?php 
            echo HEURIST_DBNAME;
            ?>
');" disabled="true" id="finished_button" style="font-weight: bold;" title="You must download non-imported records before clicking this button">
            <?php 
        }
        ?>
        <?php 
    } else {
        ?>
        <?php 
        if ($ambig_count || $session_data['non_out_entries']) {
            ?>
            <a href="interface/downloadNonImported.php/<?php 
            echo htmlspecialchars($import_id);
            ?>
-unimported.txt?import_id=<?php 
            echo htmlspecialchars($import_id);
            ?>
" onClick="elt=document.getElementById('finished_button'); if (elt) elt.disabled = false;" style="color: red;">Download non-imported records</a>
            <?php 
        }
        ?>
        <?php 
    }
    ?>
    <?php 
    if (!$ambig_count && !$session_data['non_out_entries']) {
        ?>
        <?php 
        if (@$session_data["zoteroImport"]) {
            ?>
            <input type="button" value="Finished" onClick="window.close();" style="font-weight: bold;">
            <?php 
        } else {
            ?>
            <input type="button" value="Finished" onClick="window.location.replace('importerFramework.php?db=<?php 
            echo HEURIST_DBNAME;
            ?>
');" style="font-weight: bold;">
            <?php 
        }
        ?>
        <?php 
    }
    if ($ambig_count == 0) {
        $session_data['mode'] = 'finished';
    }
}