## This file is part of Invenio.
## Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2013 CERN.
##
## Invenio is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License as
## published by the Free Software Foundation; either version 2 of the
## License, or (at your option) any later version.
##
## Invenio is distributed in the hope that it will be useful, but
## WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
## General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with Invenio; if not, write to the Free Software Foundation, Inc.,
## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.

# pylint: disable=C0103
"""Invenio BibEdit Engine."""

__revision__ = "$Id"

from datetime import datetime

import re
import zlib
import copy
import urllib
import urllib2
import cookielib

from invenio import bibformat

from invenio.errorlib import register_exception
from invenio.jsonutils import json, CFG_JSON_AVAILABLE
from invenio.urlutils import auto_version_url
from invenio.xmlmarc2textmarc import create_marc_record
from invenio.bibedit_config import CFG_BIBEDIT_AJAX_RESULT_CODES, \
    CFG_BIBEDIT_JS_CHECK_SCROLL_INTERVAL, CFG_BIBEDIT_JS_HASH_CHECK_INTERVAL, \
    CFG_BIBEDIT_JS_CLONED_RECORD_COLOR, \
    CFG_BIBEDIT_JS_CLONED_RECORD_COLOR_FADE_DURATION, \
    CFG_BIBEDIT_JS_NEW_ADD_FIELD_FORM_COLOR, \
    CFG_BIBEDIT_JS_NEW_ADD_FIELD_FORM_COLOR_FADE_DURATION, \
    CFG_BIBEDIT_JS_NEW_CONTENT_COLOR, \
    CFG_BIBEDIT_JS_NEW_CONTENT_COLOR_FADE_DURATION, \
    CFG_BIBEDIT_JS_NEW_CONTENT_HIGHLIGHT_DELAY, \
    CFG_BIBEDIT_JS_STATUS_ERROR_TIME, CFG_BIBEDIT_JS_STATUS_INFO_TIME, \
    CFG_BIBEDIT_JS_TICKET_REFRESH_DELAY, CFG_BIBEDIT_MAX_SEARCH_RESULTS, \
    CFG_BIBEDIT_TAG_FORMAT, CFG_BIBEDIT_AJAX_RESULT_CODES_REV, \
    CFG_BIBEDIT_AUTOSUGGEST_TAGS, CFG_BIBEDIT_AUTOCOMPLETE_TAGS_KBS,\
    CFG_BIBEDIT_KEYWORD_TAXONOMY, CFG_BIBEDIT_KEYWORD_TAG, \
    CFG_BIBEDIT_KEYWORD_RDFLABEL, CFG_BIBEDIT_REQUESTS_UNTIL_SAVE, \
    CFG_BIBEDIT_DOI_LOOKUP_FIELD, CFG_DOI_USER_AGENT, \
    CFG_BIBEDIT_DISPLAY_REFERENCE_TAGS, CFG_BIBEDIT_DISPLAY_AUTHOR_TAGS, \
    CFG_BIBEDIT_EXCLUDE_CURATOR_TAGS, CFG_BIBEDIT_AUTHOR_DISPLAY_THRESHOLD

from invenio.config import (CFG_SITE_LANG,
    CFG_BIBCATALOG_SYSTEM_RT_URL, CFG_BIBEDIT_SHOW_HOLDING_PEN_REMOVED_FIELDS,
    CFG_BIBCATALOG_SYSTEM, CFG_BIBEDIT_AUTOCOMPLETE)

from invenio.bibedit_dblayer import get_name_tags_all, reserve_record_id, \
    get_related_hp_changesets, get_hp_update_xml, delete_hp_change, \
    get_record_last_modification_date, get_record_revision_author, \
    get_marcxml_of_record_revision, delete_related_holdingpen_changes, \
    get_record_revisions, get_info_of_record_revision, \
    deactivate_cache

from invenio.bibedit_utils import cache_exists, cache_expired, \
    create_cache, delete_cache, get_bibrecord, \
    get_cache_contents, get_cache_mtime, get_record_templates, \
    get_record_template, latest_record_revision, record_locked_by_other_user, \
    record_locked_by_queue, save_xml_record, touch_cache, \
    update_cache_contents, get_field_templates, get_marcxml_of_revision, \
    revision_to_timestamp, timestamp_to_revision, \
    get_record_revision_timestamps, get_record_revision_authors, record_revision_exists, \
    can_record_have_physical_copies, extend_record_with_template, \
    replace_references, merge_record_with_template, record_xml_output, \
    record_is_conference, add_record_cnum, get_xml_from_textmarc, \
    record_locked_by_user_details, crossref_process_template, \
    modify_record_timestamp, get_affiliation_for_paper, InvalidCache, \
    get_new_ticket_RT_info

from invenio.bibrecord import create_record, print_rec, record_add_field, \
    record_add_subfield_into, record_delete_field, \
    record_delete_subfield_from, \
    record_modify_subfield, record_move_subfield, \
    create_field, record_replace_field, record_move_fields, \
    record_modify_controlfield, record_get_field_values, \
    record_get_subfields, record_get_field_instances, record_add_fields, \
    record_strip_empty_fields, record_strip_empty_volatile_subfields, \
    record_strip_controlfields, record_order_subfields, \
    field_add_subfield, field_get_subfield_values

from invenio.config import CFG_BIBEDIT_PROTECTED_FIELDS, CFG_CERN_SITE, \
    CFG_SITE_URL, CFG_SITE_RECORD, CFG_BIBEDIT_KB_SUBJECTS, \
    CFG_INSPIRE_SITE
from invenio.search_engine import record_exists, perform_request_search, \
    guess_primary_collection_of_a_record
from invenio.webuser import session_param_get, session_param_set
from invenio.bibcatalog import BIBCATALOG_SYSTEM
from invenio.bibcatalog_system import get_bibcat_from_prefs
from invenio.webpage import page
from invenio.htmlutils import get_mathjax_header
from invenio.textutils import wash_for_xml, show_diff
from invenio.bibknowledge import get_kbd_values_for_bibedit, get_kbr_values, \
     get_kbt_items_for_bibedit, kb_exists

from invenio.batchuploader_engine import perform_upload_check

from invenio.bibcirculation_dblayer import get_number_copies, has_copies
from invenio.bibcirculation_utils import create_item_details_url

from invenio.refextract_api import FullTextNotAvailable, \
                                   get_pdf_doc, \
                                   record_has_fulltext

from invenio import xmlmarc2textmarc as xmlmarc2textmarc
from invenio.crossrefutils import get_marcxml_for_doi, CrossrefError

import invenio.template
bibedit_templates = invenio.template.load('bibedit')

try:
    BIBCATALOG_SYSTEM.ticket_search(0)
    CFG_CAN_SEARCH_FOR_TICKET = True
except NotImplementedError:
    CFG_CAN_SEARCH_FOR_TICKET = False

re_revdate_split = re.compile(r'^(\d\d\d\d)(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)')


def bibedit_register_exception(data):
    register_exception(alert_admin=True,
                       prefix="\n".join(data['action_log']))


def get_empty_fields_templates():
    """
    Returning the templates of empty fields::
     -an empty data field
     -an empty control field
    """
    return [{
                "name": "Empty field",
                "description": "The data field not containing any " +
                               "information filled in",
                "tag" : "",
                "ind1" : "",
                "ind2" : "",
                "subfields" : [("", "")],
                "isControlfield" : False
            }, {
                "name" : "Empty control field",
                "description" : "The controlfield not containing any " +
                                "data or tag description",
                "isControlfield" : True,
                "tag" : "",
                "value" : ""
            }]

def get_available_fields_templates():
    """
    A method returning all the available field templates
    Returns a list of descriptors. Each descriptor has
    the same structure as a full field descriptor inside the
    record
    """
    templates = get_field_templates()
    result = get_empty_fields_templates()
    for template in templates:
        tplTag = template[3].keys()[0]
        field = template[3][tplTag][0]

        if (field[0] == []):
        # if the field is a controlField, add different structure
            result.append({
                    "name" : template[1],
                    "description" : template[2],
                    "isControlfield" : True,
                    "tag" : tplTag,
                    "value" : field[3]
                })
   
     else:
            result.append({
                    "name": template[1],
                    "description": template[2],
                    "tag" : tplTag,
                    "ind1" : field[1],
                    "ind2" : field[2],
                    "subfields" : field[0],
                    "isControlfield" : False
      
              })
    return result

def perform_request_init(uid, ln, req, lastupdated):
    """Handle the initial request by adding menu and JavaScript to the page."""
    errors   = []
    warnings = []
    body = 