# -*- coding: utf-8 -*-

from collections import OrderedDict

from gluon import current, URL
from gluon.storage import Storage

def config(settings):
    """
        Template settings for SaFiRe: Sahana First Response

        http://eden.sahanafoundation.org/wiki/BluePrint/SAFIRE
    """

    T = current.T

    settings.base.system_name = T("Sahana First Response")
    settings.base.system_name_short = T("SAFIRE")

    # PrePopulate data
    settings.base.prepopulate.append("SAFIRE")
    settings.base.prepopulate_demo.append("SAFIRE/Demo")

    # Theme (folder to use for views/layout.html)
    #settings.base.theme = "SAFIRE"

    # Authentication settings
    # Should users be allowed to register themselves?
    #settings.security.self_registration = False
    # Do new users need to verify their email address?
    #settings.auth.registration_requires_verification = True
    # Do new users need to be approved by an administrator prior to being able to login?
    #settings.auth.registration_requires_approval = True
    settings.auth.registration_requests_organisation = True

    # Approval emails get sent to all admins
    settings.mail.approver = "ADMIN"

    settings.auth.registration_link_user_to = {"staff": T("Staff"),
                                               }

    settings.auth.registration_link_user_to_default = ["staff"]

    # Uncomment to display the Map Legend as a floating DIV
    settings.gis.legend = "float"
    # Uncomment to Disable the Postcode selector in the LocationSelector
    #settings.gis.postcode_selector = False # @ToDo: Vary by country (include in the gis_config!)
    # Uncomment to show the Print control:
    # http://eden.sahanafoundation.org/wiki/UserGuidelines/Admin/MapPrinting
    #settings.gis.print_button = True

    # GeoNames username
    settings.gis.geonames_username = "trendspotter"
    settings.gis.simplify_tolerance = 0

    # L10n settings
    # Number formats (defaults to ISO 31-0)
    # Decimal separator for numbers (defaults to ,)
    settings.L10n.decimal_separator = "."
    # Thousands separator for numbers (defaults to space)
    settings.L10n.thousands_separator = ","

    # Security Policy
    # http://eden.sahanafoundation.org/wiki/S3AAA#System-widePolicy
    # 1: Simple (default): Global as Reader, Authenticated as Editor
    # 2: Editor role required for Update/Delete, unless record owned by session
    # 3: Apply Controller ACLs
    # 4: Apply both Controller & Function ACLs
    # 5: Apply Controller, Function & Table ACLs
    # 6: Apply Controller, Function, Table ACLs and Entity Realm
    # 7: Apply Controller, Function, Table ACLs and Entity Realm + Hierarchy
    # 8: Apply Controller, Function, Table ACLs, Entity Realm + Hierarchy and Delegations

    settings.security.policy = 5 # Controller, Function & Table ACLs

    # -------------------------------------------------------------------------
    # Comment/uncomment modules here to disable/enable them
    # Modules menu is defined in modules/eden/menu.py
    settings.modules = OrderedDict([
        # Core modules which shouldn't be disabled
        ("default", Storage(
            name_nice = "Home",
            restricted = False, # Use ACLs to control access to this module
            #access = None,      # All Users (inc Anonymous) can see this module in the default menu & access the controller
            module_type = None  # This item is not shown in the menu
        )),
        ("admin", Storage(
            name_nice = "Administration",
            #description = "Site Administration",
            access = "|1|",     # Only Administrators can see this module in the default menu & access the controller
            module_type = None  # This item is handled separately for the menu
        )),
        ("appadmin", Storage(
            name_nice = "Administration",
            #description = "Site Administration",
            module_type = None  # No Menu
        )),
        ("errors", Storage(
            name_nice = "Ticket Viewer",
            #description = "Needed for Breadcrumbs",
            restricted = False,
            module_type = None  # No Menu
        )),
        ("sync", Storage(
            name_nice = "Synchronization",
            #description = "Synchronization",
            access = "|1|",     # Only Administrators can see this module in the default menu & access the controller
            module_type = None  # This item is handled separately for the menu
        )),
        #("tour", Storage(
        #    name_nice = T("Guided Tour Functionality"),
        #    module_type = None,
        #)),
        #("translate", Storage(
        #    name_nice = T("Translation Functionality"),
        #    #description = "Selective translation of strings based on module.",
        #    module_type = None,
        #)),
        ("gis", Storage(
            name_nice = "Map",
            #description = "Situation Awareness & Geospatial Analysis",
            module_type = 6,     # 6th item in the menu
        )),
        ("pr", Storage(
            name_nice = "Person Registry",
            #description = "Central point to record details on People",
            access = "|1|",     # Only Administrators can see this module in the default menu (access to controller is possible to all still)
            module_type = 10
        )),
        ("org", Storage(
            name_nice = "Organizations",
            #description = 'Lists "who is doing what & where". Allows relief agencies to coordinate their activities',
            module_type = 1
        )),
        ("hrm", Storage(
            name_nice = "Staff",
            #description = "Human Resources Management",
            module_type = 2,
        )),
        ("vol", Storage(
            name_nice = T("Volunteers"),
            #description = "Human Resources Management",
            module_type = 2,
        )),
        ("cms", Storage(
            name_nice = "Content Management",
            #description = "Content Management System",
            module_type = 10,
        )),
        ("doc", Storage(
            name_nice = "Documents",
            #description = "A library of digital resources, such as photos, documents and reports",
            module_type = 10,
        )),
        ("msg", Storage(
            name_nice = "Messaging",
            #description = "Sends & Receives Alerts via Email & SMS",
            # The user-visible functionality of this module isn't normally required. Rather it's main purpose is to be accessed from other modules.
            module_type = None,
        )),
        ("supply", Storage(
            name_nice = "Supply Chain Management",
            #description = "Used within Inventory Management, Request Management and Asset Management",
            module_type = None, # Not displayed
        )),
        ("inv", Storage(
            name_nice = T("Warehouses"),
            #description = "Receiving and Sending Items",
            module_type = 4
        )),
        ("asset", Storage(
            name_nice = "Assets",
            #description = "Recording and Assigning Assets",
            module_type = 5,
        )),
        # Vehicle depends on Assets
        ("vehicle", Storage(
            name_nice = "Vehicles",
            #description = "Manage Vehicles",
            module_type = 10,
        )),
        #("budget", Storage(
        #    name_nice = T("Budgets"),
        #    #description = "Tracks the location, capacity and breakdown of victims in Shelters",
        #    module_type = 10
        #)),
        ("fin", Storage(
            name_nice = T("Finance"),
            module_type = 10
        )),
        ("cr", Storage(
            name_nice = T("Shelters"),
            #description = "Tracks the location, capacity and breakdown of victims in Shelters",
            module_type = 10
        )),
        ("project", Storage(
            name_nice = "Tasks",
            #description = "Tracking of Projects, Activities and Tasks",
            module_type = 2
        )),
        ("req", Storage(
            name_nice = "Requests",
            #description = "Manage requests for supplies, assets, staff or other resources. Matches against Inventories where supplies are requested.",
            module_type = 10,
        )),
        ("hms", Storage(
            name_nice = T("Hospitals"),
            #description = "Helps to monitor status of hospitals",
            module_type = 10
        )),
        #("dvr", Storage(
        #   name_nice = T("Disaster Victim Registry"),
        #   #description = "Allow affected individuals & households to register to receive compensation and distributions",
        #   module_type = 10,
        #)),
        ("event", Storage(
            name_nice = "Events",
            #description = "Activate Events (e.g. from Scenario templates) for allocation of appropriate Resources (Human, Assets & Facilities).",
            module_type = 10,
        )),
        #("transport", Storage(
        #   name_nice = T("Transport"),
        #   module_type = 10,
        #)),
        #("stats", Storage(
        #    name_nice = T("Statistics"),
        #    #description = "Manages statistics",
        #    module_type = None,
        #)),
    ])

    # -------------------------------------------------------------------------
    # CMS
    # -------------------------------------------------------------------------
    settings.cms.richtext = True

    # -------------------------------------------------------------------------
    # Organisations
    # -------------------------------------------------------------------------
    settings.org.documents_tab = True
    settings.org.projects_tab = False

    # -------------------------------------------------------------------------
    # Shelters
    # -------------------------------------------------------------------------
    settings.cr.people_registration = False

    # -------------------------------------------------------------------------
    def customise_cr_shelter_resource(r, tablename):

        #table = current.s3db.cr_shelter
        f = current.s3db.cr_shelter.shelter_service_id
        f.readable = f.writable = False

    settings.customise_cr_shelter_resource = customise_cr_shelter_resource

    # -------------------------------------------------------------------------
    # Events
    # -------------------------------------------------------------------------
    def event_rheader(r):
        rheader = None

        record = r.record
        if record and r.representation == "html":

            from gluon import A, DIV, TABLE, TR, TH
            from s3 import s3_rheader_tabs

            name = r.name
            if name == "incident":
                if settings.get_incident_label(): # == "Ticket"
                    label = T("Ticket Details")
                else:
                    label = T("Incident Details")
                tabs = [(label, None),
                        #(T("Tasks"), "task"),
                        #(T("Human Resources"), "human_resource"),
                        #(T("Equipment"), "asset"),
                        (T("Action Plan"), "plan"),
                        (T("Incident Reports"), "incident_report"),
                        (T("Logs"), "log"),
                        (T("Expenses"), "expense"),
                        (T("Situation Reports"), "sitrep"),
                        ]

                rheader_tabs = s3_rheader_tabs(r, tabs)

                record_id = r.id
                incident_type_id = record.incident_type_id

                editable = current.auth.s3_has_permission("UPDATE", "event_incident", record_id)

                if editable:
                    # Dropdown of Scenarios to select
                    stable = current.s3db.event_scenario
                    query = (stable.incident_type_id == incident_type_id) & \
                            (stable.deleted == False)
                    scenarios = current.db(query).select(stable.id,
                                                         stable.name,
                                                         )
                    if len(scenarios) and r.method != "event":
                        from gluon import SELECT, OPTION
                        dropdown = SELECT(_id="scenarios")
                        dropdown["_data-incident_id"] = record_id
                        dappend = dropdown.append
                        dappend(OPTION(T("Select Scenario")))
                        for s in scenarios:
                            dappend(OPTION(s.name, _value=s.id))
                        scenarios = TR(TH("%s: " % T("Scenario")),
                                       dropdown,
                                       )
                        s3 = current.response.s3
                        script = "/%s/static/themes/SAFIRE/js/incident_profile.js" % r.application
                        if script not in s3.scripts:
                            s3.scripts.append(script)
                            s3.js_global.append('''i18n.scenarioConfirm="%s"''' % T("Populate Incident with Tasks, Organizations, Positions and Equipment from the Scenario?"))
                    else:
                        scenarios = ""
                else:
                    scenarios = ""

                if record.exercise:
                    exercise = TH(T("EXERCISE"))
                else:
                    exercise = TH()
                if record.closed:
                    closed = TH(T("CLOSED"))
                else:
                    closed = TH()

                if record.event_id or r.method == "event" or not editable:
                    event = ""
                else:
                    if settings.get_event_label(): # == "Disaster"
                        label = T("Assign to Disaster")
                    else:
                        label = T("Assign to Event")
                    event = A(label,
                              _href = URL(c = "event",
                                          f = "incident",
                                          args = [record_id, "event"],
                                          ),
                              _class = "action-btn"
                              )

                table = r.table
                rheader = DIV(TABLE(TR(exercise),
                                    TR(TH("%s: " % table.name.label),
                                       record.name,
                                       ),
                                    TR(TH("%s: " % table.incident_type_id.label),
                                       table.incident_type_id.represent(incident_type_id),
                                       ),
                                    TR(TH("%s: " % table.location_id.label),
                                       table.location_id.represent(record.location_id),
                                       ),
                                    # @ToDo: Add Zone
                                    TR(TH("%s: " % table.severity.label),
                                       table.severity.represent(record.severity),
                                       ),
                                    TR(TH("%s: " % table.level.label),
                                       table.level.represent(record.level),
                                       ),
                                    TR(TH("%s: " % table.organisation_id.label),
                                       table.organisation_id.represent(record.organisation_id),
                                       ),
                                    TR(TH("%s: " % table.person_id.label),
                                       table.person_id.represent(record.person_id),
                                       ),
                                    scenarios,
                                    TR(TH("%s: " % table.comments.label),
                                       record.comments,
                                       ),
                                    TR(TH("%s: " % table.date.label),
                                       table.date.represent(record.date),
                                       ),
                                    TR(closed),
                                    event,
                                    ), rheader_tabs)

            elif name == "incident_report":
                record_id = r.id
                ltable = current.s3db.event_incident_report_incident
                query = (ltable.incident_report_id == record_id)
                link = current.db(query).select(ltable.incident_id,
                                                limitby = (0, 1)
                                                ).first()
                if link:
                    from s3 import S3Represent
                    represent = S3Represent(lookup="event_incident", show_link=True)
                    rheader = DIV(TABLE(TR(TH("%s: " % ltable.incident_id.label),
                                           represent(link.incident_id),
                                           ),
                                        ))
                else:
                    if settings.get_incident_label(): # == "Ticket"
                        label = T("Assign to Ticket")
                    else:
                        label = T("Assign to Incident")
                    rheader = DIV(A(label,
                                    _href = URL(c = "event",
                                                f = "incident_report",
                                                args = [record_id, "assign"],
                                                ),
                                    _class = "action-btn"
                                    ))

            elif name == "event":
                if settings.get_event_label(): # == "Disaster"
                    label = T("Disaster Details")
                else:
                    label = T("Event Details")
                if settings.get_incident_label(): # == "Ticket"
                    INCIDENTS = T("Tickets")
                else:
                    INCIDENTS = T("Incidents")
                tabs = [(label, None),
                        (INCIDENTS, "incident"),
                        (T("Documents"), "document"),
                        (T("Photos"), "image"),
                        ]

                rheader_tabs = s3_rheader_tabs(r, tabs)

                table = r.table
                rheader = DIV(TABLE(TR(TH("%s: " % table.event_type_id.label),
                                       table.event_type_id.represent(record.event_type_id),
                                       ),
                                    TR(TH("%s: " % table.name.label),
                                       record.name,
                                       ),
                                    TR(TH("%s: " % table.start_date.label),
                                       table.start_date.represent(record.start_date),
                                       ),
                                    TR(TH("%s: " % table.comments.label),
                                       record.comments,
                                       ),
                                    ), rheader_tabs)

            elif name == "scenario":
                tabs = [(T("Scenario Details"), None),
                        #(T("Tasks"), "task"),
                        #(T("Human Resources"), "human_resource"),
                        #(T("Equipment"), "asset"),
                        (T("Action Plan"), "plan"),
                        (T("Incident Reports"), "incident_report"),
                        ]

                rheader_tabs = s3_rheader_tabs(r, tabs)

                table = r.table
                rheader = DIV(TABLE(TR(TH("%s: " % table.incident_type_id.label),
                                       table.incident_type_id.represent(record.incident_type_id),
                                       ),
                                    TR(TH("%s: " % table.organisation_id.label),
                                       table.organisation_id.represent(record.organisation_id),
                                       ),
                                    TR(TH("%s: " % table.location_id.label),
                                       table.location_id.represent(record.location_id),
                                       ),
                                    TR(TH("%s: " % table.name.label),
                                       record.name,
                                       ),
                                    TR(TH("%s: " % table.comments.label),
                                       record.comments,
                                       ),
                                    ), rheader_tabs)

        return rheader

    # -------------------------------------------------------------------------
    def customise_event_event_controller(**attr):

        #s3 = current.response.s3

        # No sidebar menu
        #current.menu.options = None
        attr["rheader"] = event_rheader

        return attr

    settings.customise_event_event_controller = customise_event_event_controller

    # -------------------------------------------------------------------------
    def customise_event_incident_report_resource(r, tablename):

        current.response.s3.crud_strings[tablename] = Storage(
            label_create = T("Log Call"),
            title_display = T("Call Log Details"),
            title_list = T("Call Logs"),
            title_update = T("Edit Call Log"),
            label_list_button = T("List Call Logs"),
            label_delete_button = T("Delete Call Log"),
            msg_record_created = T("Call Log added"),
            msg_record_modified = T("Call Log updated"),
            msg_record_deleted = T("Call Log removed"),
            msg_list_empty = T("No Calls currently logged"),
            )

    settings.customise_event_incident_report_resource = customise_event_incident_report_resource

    # -------------------------------------------------------------------------
    def customise_event_incident_report_controller(**attr):

        from gluon import A

        s3 = current.response.s3

        # Custom prep
        standard_prep = s3.prep
        def custom_prep(r):
            # Call standard postp
            if callable(standard_prep):
                result = standard_prep(r)
                if not result:
                    return False

            method = r.method
            if method in (None, "create"):
                current.s3db.gis_location.addr_street.label = T("Street Address or Location Details")
                from s3 import S3SQLCustomForm
                crud_form = S3SQLCustomForm((T("What is it?"), "name"),
                                            "incident_type_id",
                                            (T("Who am I speaking with?"), "reported_by"),
                                            (T("How can we contact you?"), "contact"),
                                            (T("Where did this Incident take place?"), "location_id"),
                                            (T("Explain the Situation?"), "description"),
                                            (T("What are your immediate needs?"), "needs"),
                                            )
                r.resource.configure(create_next = URL(args=["[id]", "assign"]),
                                     crud_form = crud_form,
                                     )

            return True
        s3.prep = custom_prep

        # No sidebar menu
        current.menu.options = None
        req_args = current.request.args
        if len(req_args) > 1 and req_args[1] == "assign":
            if settings.get_incident_label(): # == "Ticket"
                label = T("New Ticket")
            else:
                label = T("New Incident")
            attr["rheader"] = A(label,
                                _class = "action-btn",
                                _href = URL(c="event", f="incident",
                                            args = ["create"],
                                            vars = {"incident_report_id": req_args[0]},
                                            ),
                                )
        else:
            attr["rheader"] = event_rheader

        return attr

    settings.customise_event_incident_report_controller = customise_event_incident_report_controller

    # -------------------------------------------------------------------------
    def event_incident_create_onaccept(form):
        """
            Automate Level based on Type, Zone (intersect from Location) & Severity
            @ToDo: Move this to SAFIRE/SC
        """

        db = current.db
        s3db = current.s3db

        form_vars_get = form.vars.get
        incident_id = form_vars_get("id")

        # If Incident Type is Chemical then level must be > 2
        level = form_vars_get("level")
        if level and int(level) < 3:
            incident_type_id = form_vars_get("incident_type_id")
            ittable = s3db.event_incident_type
            incident_type = db(ittable.id == incident_type_id).select(ittable.name,
                                                                      limitby = (0,1)
                                                                      ).first().name
            if incident_type == "Chemical Hazard":
                itable = s3db.event_incident
                db(itable.id == incident_id).update(level = 3)
                current.response.warning = T("Chemical Hazard Incident so Level raised to 3")

        # Alert Lead Agency
        organisation_id = form_vars_get("organisation_id")
        if organisation_id:
            otable = s3db.org_organisation_tag
            query = (otable.organisation_id == organisation_id) & \
                    (otable.tag == "duty")
            duty = db(query).select(otable.value,
                                    limitby = (0, 1)
                                    ).first()
            if duty:
                current.msg.send_sms_via_api(duty.value,
                    "You have been assigned an Incident: %s%s" % (settings.get_base_public_url(),
                                                                  URL(c="event", f= "incident",
                                                                      args = incident_id),
                                                                  ))

    # -------------------------------------------------------------------------
    def customise_event_incident_resource(r, tablename):

        from s3 import S3LocationSelector

        s3db = current.s3db

        table = s3db.event_incident
        f = table.severity
        f.readable = f.writable = True
        f = table.level
        f.readable = f.writable = True
        table.location_id.widget = S3LocationSelector(polygons = True,
                                                      show_address = True,
                                                      )
        f = table.organisation_id
        f.readable = f.writable = True
        f.label = T("Lead Response Organization")
        if r.method == "plan":
            table.action_plan.label = T("Event Action Plan")
        else:
            f = table.action_plan
            f.readable = f.writable = False

        if r.interactive:
            s3db.add_custom_callback(tablename,
                                     "create_onaccept",
                                     event_incident_create_onaccept,
                                     )

    settings.customise_event_incident_resource = customise_event_incident_resource

    # -------------------------------------------------------------------------
    def customise_event_incident_controller(**attr):

        s3db = current.s3db
        s3 = current.response.s3

        # Custom prep
        standard_prep = s3.prep
        def custom_prep(r):
            # Call standard postp
            if callable(standard_prep):
                result = standard_prep(r)
                if not result:
                    return False

            resource = r.resource

            # Redirect to action plan after create
            resource.configure(create_next = URL(c="event", f="incident",
                                                 args = ["[id]", "plan"]),
                               )

            method = r.method
            if method == "create":
                incident_report_id = r.get_vars.get("incident_report_id")
                if incident_report_id:
                    # Got here from incident report assign => "New Incident"
                    # - prepopulate incident name from report title
                    # - copy incident type and location from report
                    # - onaccept: link the incident report to the incident
                    if r.http == "GET":
                        from s3 import s3_truncate
                        rtable = s3db.event_incident_report
                        incident_report = current.db(rtable.id == incident_report_id).select(rtable.name,
                                                                                             rtable.incident_type_id,
                                                                                             rtable.location_id,
                                                                                             limitby = (0, 1),
                                                                                             ).first()
                        table = r.table
                        table.name.default = s3_truncate(incident_report.name, 64)
                        table.incident_type_id.default = incident_report.incident_type_id
                        table.location_id.default = incident_report.location_id

                    elif r.http == "POST":
                        def create_onaccept(form):
                            s3db.event_incident_report_incident.insert(incident_id = form.vars.id,
                                                                       incident_report_id = incident_report_id,
                                                                       )

                        s3db.add_custom_callback("event_incident",
                                                 "create_onaccept",
                                                 create_onaccept,
                                                 )

            elif method == "plan" and settings.get_incident_label(): # == "Ticket"
                s3db.event_task
                s3db.event_organisation
                crud_strings = s3.crud_strings
                crud_strings.event_task.msg_list_empty = T("No Tasks currently registered for this ticket")
                crud_strings.event_organisation.msg_list_empty = T("No Organizations currently registered in this ticket")

            return True
        s3.prep = custom_prep

        # No sidebar menu
        current.menu.options = None
        attr["rheader"] = event_rheader

        return attr

    settings.customise_event_incident_controller = customise_event_incident_controller

    # -------------------------------------------------------------------------
    def customise_event_asset_resource(r, tablename):

        table = current.s3db.event_asset
        table.item_id.label = T("Item Type")
        table.asset_id.label = T("Specific Item")
        # DateTime
        from gluon import IS_EMPTY_OR
        from s3 import IS_UTC_DATETIME, S3CalendarWidget, S3DateTime
        for f in (table.start_date, table.end_date):
            f.requires = IS_EMPTY_OR(IS_UTC_DATETIME())
            f.represent = lambda dt: S3DateTime.datetime_represent(dt, utc=True)
            f.widget = S3CalendarWidget(timepicker = True)

        if settings.get_incident_label(): # == "Ticket"
            current.response.s3.crud_strings[tablename] = Storage(
                label_create = T("Add Equipment"),
                title_display = T("Equipment Details"),
                title_list = T("Equipment"),
                title_update = T("Edit Equipment"),
                label_list_button = T("List Equipment"),
                label_delete_button = T("Remove Equipment from this ticket"),
                msg_record_created = T("Equipment added"),
                msg_record_modified = T("Equipment updated"),
                msg_record_deleted = T("Equipment removed"),
                msg_list_empty = T("No Equipment currently registered for this ticket"))
        else:
            current.response.s3.crud_strings[tablename] = Storage(
                label_create = T("Add Equipment"),
                title_display = T("Equipment Details"),
                title_list = T("Equipment"),
                title_update = T("Edit Equipment"),
                label_list_button = T("List Equipment"),
                label_delete_button = T("Remove Equipment from this incident"),
                msg_record_created = T("Equipment added"),
                msg_record_modified = T("Equipment updated"),
                msg_record_deleted = T("Equipment removed"),
                msg_list_empty = T("No Equipment currently registered for this incident"))

    settings.customise_event_asset_resource = customise_event_asset_resource

    # -------------------------------------------------------------------------
    def event_human_resource_onaccept(form, create=True):
        """
            When a Position is assigned to an Incident:
             - set_event_from_incident
             - add Log Entry
             - send Notification
        """

        db = current.db
        s3db = current.s3db

        s3db.event_set_event_from_incident(form, "event_human_resource")

        table = s3db.event_human_resource

        form_vars = form.vars
        form_vars_get = form_vars.get
        link_id = form_vars_get("id")
        incident_id = form_vars_get("incident_id")
        if not incident_id:
            link = db(table.id == link_id).select(table.incident_id,
                                                  limitby = (0, 1)
                                                  ).first()
            incident_id = link.incident_id

        pe_id = None
        if create:
            person_id = form_vars_get("person_id")
            if person_id:
                ptable = s3db.pr_person
                person = db(ptable.id == person_id).select(ptable.pe_id,
                                                           limitby = (0, 1)
                                                           ).first()
                pe_id = person.pe_id

            job_title_id = form_vars_get("job_title_id")
            if job_title_id:
                s3db.event_incident_log.insert(incident_id = incident_id,
                                               name = "Person Requested",
                                               comments = s3db.event_human_resource.job_title_id.represent(job_title_id),
                                               )
        else:
            # Update
            record = form.record
            if record: # Not True for a record merger
                from s3dal import Field
                changed = {}
                for var in form_vars:
                    vvar = form_vars[var]
                    if isinstance(vvar, Field):
                        # modified_by/modified_on
                        continue
                    rvar = record.get(var, "NOT_PRESENT")
                    if rvar != "NOT_PRESENT" and vvar != rvar:
                        f = table[var]
                        if var == "pe_id":
                            pe_id = vvar
                        type_ = f.type
                        if type_ == "integer" or \
                           type_.startswith("reference"):
                            if vvar:
                                vvar = int(vvar)
                            if vvar == rvar:
                                continue
                        represent = table[var].represent
                        if represent:
                            if hasattr(represent, "show_link"):
                                represent.show_link = False
                        else:
                            represent = lambda o: o
                        if rvar:
                            changed[var] = "%s changed from %s to %s" % \
                                (f.label, represent(rvar), represent(vvar))
                        else:
                            changed[var] = "%s changed to %s" % \
                                (f.label, represent(vvar))

                if changed:
                    table = s3db.event_incident_log
                    text = []
                    for var in changed:
                        text.append(changed[var])
                    text = "\n".join(text)
                    table.insert(incident_id = incident_id,
                                 #name = "Person Assigned",
                                 name = "Person Request Updated",
                                 comments = text,
                                 )

        if pe_id:
            # Notify Assignee
            if settings.get_incident_label(): # == "Ticket"
                label = T("Ticket")
            else:
                label = T("Incident")
            current.msg.send_by_pe_id(pe_id,
                                      subject = "",
                                      message = "You have been assigned to an %s: %s%s" % \
                                        (label,
                                         settings.get_base_public_url(),
                                         URL(c="event", f= "incident",
                                             args = [incident_id, "human_resource", link_id]),
                                             ),
                                      contact_method = "SMS")

    # -------------------------------------------------------------------------
    def customise_event_human_resource_resource(r, tablename):

        s3db = current.s3db
        table = s3db.event_human_resource
        # DateTime
        from gluon import IS_EMPTY_OR
        from s3 import IS_UTC_DATETIME, S3CalendarWidget, S3DateTime
        for f in (table.start_date, table.end_date):
            f.requires = IS_EMPTY_OR(IS_UTC_DATETIME())
            f.represent = lambda dt: S3DateTime.datetime_represent(dt, utc=True)
            f.widget = S3CalendarWidget(timepicker = True)

        if settings.get_incident_label(): # == "Ticket"
            current.response.s3.crud_strings[tablename] = Storage(
                label_create = T("Add Person"),
                title_display = T("Person Details"),
                title_list = T("Personnel"),
                title_update = T("Edit Person"),
                label_list_button = T("List Personnel"),
                label_delete_button = T("Remove Person from this ticket"),
                msg_record_created = T("Person added"),
                msg_record_modified = T("Person updated"),
                msg_record_deleted = T("Person removed"),
                msg_list_empty = T("No Persons currently registered for this ticket"))
        else:
            current.response.s3.crud_strings[tablename] = Storage(
                label_create = T("Add Person"),
                title_display = T("Person Details"),
                title_list = T("Personnel"),
                title_update = T("Edit Person"),
                label_list_button = T("List Personnel"),
                label_delete_button = T("Remove Person from this incident"),
                msg_record_created = T("Person added"),
                msg_record_modified = T("Person updated"),
                msg_record_deleted = T("Person removed"),
                msg_list_empty = T("No Persons currently registered for this incident"))

        s3db.configure(tablename,
                       # Deliberately over-rides
                       create_onaccept = event_human_resource_onaccept,
                       update_onaccept = lambda form:
                            event_human_resource_onaccept(form, create=False),
                       )

    settings.customise_event_human_resource_resource = customise_event_human_resource_resource

    # -------------------------------------------------------------------------
    def customise_event_scenario_controller(**attr):

        s3 = current.response.s3

        # Custom prep
        standard_prep = s3.prep
        def custom_prep(r):
            # Call standard postp
            if callable(standard_prep):
                result = standard_prep(r)
                if not result:
                    return False

            if r.method != "plan":
                f = r.table.action_plan
                f.readable = f.writable = False

            if r.method == "create"and r.http == "POST":
                r.resource.configure(create_next = URL(c="event", f="scenario",
                                                       args = ["[id]", "plan"]),
                                     )

            return True
        s3.prep = custom_prep

        # No sidebar menu
        current.menu.options = None
        attr["rheader"] = event_rheader

        return attr

    settings.customise_event_scenario_controller = customise_event_scenario_controller

    # -------------------------------------------------------------------------
    def customise_event_scenario_asset_resource(r, tablename):

        table = current.s3db.event_scenario_asset
        table.item_id.label = T("Item Type")
        table.asset_id.label = T("Specific Item")

        if settings.get_incident_label(): # == "Ticket"
            current.response.s3.crud_strings[tablename] = Storage(
                label_create = T("Add Equipment"),
                title_display = T("Equipment Details"),
                title_list = T("Equipment"),
                title_update = T("Edit Equipment"),
                label_list_button = T("List Equipment"),
                label_delete_button = T("Remove Equipment from this ticket"),
                msg_record_created = T("Equipment added"),
                msg_record_modified = T("Equipment updated"),
                msg_record_deleted = T("Equipment removed"),
                msg_list_empty = T("No Equipment currently registered for this ticket"))
        else:
            current.response.s3.crud_strings[tablename] = Storage(
                label_create = T("Add Equipment"),
                title_display = T("Equipment Details"),
                title_list = T("Equipment"),
                title_update = T("Edit Equipment"),
                label_list_button = T("List Equipment"),
                label_delete_button = T("Remove Equipment from this incident"),
                msg_record_created = T("Equipment added"),
                msg_record_modified = T("Equipment updated"),
                msg_record_deleted = T("Equipment removed"),
                msg_list_empty = T("No Equipment currently registered for this incident"))

    settings.customise_event_scenario_asset_resource = customise_event_scenario_asset_resource

    # -------------------------------------------------------------------------
    def customise_event_scenario_human_resource_resource(r, tablename):

        if settings.get_incident_label(): # == "Ticket"
            current.response.s3.crud_strings[tablename] = Storage(
                label_create = T("Add Person"),
                title_display = T("Person Details"),
                title_list = T("Personnel"),
                title_update = T("Edit Person"),
                label_list_button = T("List Personnel"),
                label_delete_button = T("Remove Person from this ticket"),
                msg_record_created = T("Person added"),
                msg_record_modified = T("Person updated"),
                msg_record_deleted = T("Person removed"),
                msg_list_empty = T("No Persons currently registered for this ticket"))
        else:
            current.response.s3.crud_strings[tablename] = Storage(
                label_create = T("Add Person"),
                title_display = T("Person Details"),
                title_list = T("Personnel"),
                title_update = T("Edit Person"),
                label_list_button = T("List Personnel"),
                label_delete_button = T("Remove Person from this incident"),
                msg_record_created = T("Person added"),
                msg_record_modified = T("Person updated"),
                msg_record_deleted = T("Person removed"),
                msg_list_empty = T("No Persons currently registered for this incident"))

    settings.customise_event_scenario_human_resource_resource = customise_event_scenario_human_resource_resource

    # -------------------------------------------------------------------------
    # HRM
    # -------------------------------------------------------------------------
    settings.hrm.job_title_deploy = True
    settings.hrm.org_dependent_job_titles = True

    # -------------------------------------------------------------------------
    # Organisations
    # -------------------------------------------------------------------------

    # -------------------------------------------------------------------------
    def customise_org_organisation_resource(r, tablename):

        s3db = current.s3db

        # Custom Components
        s3db.add_components(tablename,
                            org_organisation_tag = (# On-call Duty Number
                                                    {"name": "duty",
                                                     "joinby": "organisation_id",
                                                     "filterby": {"tag": "duty",
                                                                  },
                                                     "multiple": False,
                                                     },
                                                    ),
                            )

        from s3 import S3SQLCustomForm, S3SQLInlineComponent, S3SQLInlineLink, \
                       IS_EMPTY_OR, IS_PHONE_NUMBER_MULTI, S3PhoneWidget, s3_phone_represent

        # Individual settings for specific tag components
        components_get = s3db.resource(tablename).components.get

        duty = components_get("duty")
        f = duty.table.value
        f.represent = s3_phone_represent,
        f.requires = IS_EMPTY_OR(IS_PHONE_NUMBER_MULTI())
        f.widget = S3PhoneWidget()

        crud_form = S3SQLCustomForm("name",
                                    "acronym",
                                    S3SQLInlineLink("organisation_type",
                                                    field = "organisation_type_id",
                                                    # Default 10 options just triggers which adds unnecessary complexity to a commonly-used form & commonly an early one (create Org when registering)
                                                    search = False,
                                                    label = T("Type"),
                                                    multiple = False,
                                                    widget = "multiselect",
                                                    ),
                                    "country",
                                    (T("Reception Phone #"), "phone"),
                                    S3SQLInlineComponent("duty",
                                                         label = T("On-call Duty Number"),
                                                         fields = [("", "value")],
                                                         multiple = False,
                                                         ),
                                    "website",
                                    "logo",
                                    "comments",
                                    )

        s3db.configure(tablename,
                       crud_form = crud_form,
                       )

    settings.customise_org_organisation_resource = customise_org_organisation_resource

    # -------------------------------------------------------------------------
    # Projects
    # -------------------------------------------------------------------------

    # -------------------------------------------------------------------------
    def project_task_onaccept(form, create=True):
        """
            Send Person a Notification when they are assigned to a Task
            Log changes in Incident Log
        """

        if current.request.function == "scenario":
            # Must be a Scenario
            # - don't Log
            # - don't send Notification
            return

        db = current.db
        s3db = current.s3db
        ltable = s3db.event_task

        form_vars = form.vars
        form_vars_get = form_vars.get
        task_id = form_vars_get("id")
        link = db(ltable.task_id == task_id).select(ltable.incident_id,
                                                    limitby = (0, 1)
                                                    ).first()
        if not link:
            # Not attached to an Incident
            # - don't Log
            # - don't send Notification
            return

        incident_id = link.incident_id

        if create:
            pe_id = form_vars_get("pe_id")
            # Log
            name = form_vars_get("name")
            if name:
                s3db.event_incident_log.insert(incident_id = incident_id,
                                               name = "Task Created",
                                               comments = name,
                                               )

        else:
            # Update
            pe_id = None
            record = form.record
            if record: # Not True for a record merger
                from s3dal import Field
                table = s3db.project_task
                changed = {}
                for var in form_vars:
                    vvar = form_vars[var]
                    if isinstance(vvar, Field):
                        # modified_by/modified_on
                        continue
                    if var == "pe_id":
                        pe_id = vvar
                    rvar = record.get(var, "NOT_PRESENT")
                    if rvar != "NOT_PRESENT" and vvar != rvar:
                        f = table[var]
                        type_ = f.type
                        if type_ == "integer" or \
                           type_.startswith("reference"):
                            if vvar:
                                vvar = int(vvar)
                            if vvar == rvar:
                                continue
                        represent = table[var].represent
                        if represent:
                            if hasattr(represent, "show_link"):
                                represent.show_link = False
                        else:
                            represent = lambda o: o
                        if rvar:
                            changed[var] = "%s changed from %s to %s" % \
                                (f.label, represent(rvar), represent(vvar))
                        else:
                            changed[var] = "%s changed to %s" % \
                                (f.label, represent(vvar))

                if changed:
                    table = s3db.event_incident_log
                    text = []
                    for var in changed:
                        text.append(changed[var])
                    text = "\n".join(text)
                    table.insert(incident_id = incident_id,
                                 name = "Task Updated",
                                 comments = text,
                                 )

        if pe_id:
            # Notify Assignee
            message = "You have been assigned a Task: %s%s" % \
                        (settings.get_base_public_url(),
                         URL(c="event", f= "incident",
                             args = [incident_id, "task", task_id]),
                             )
            instance_type = s3db.pr_instance_type(pe_id)
            if instance_type == "org_organisation":
                # Notify the Duty Number for the Organisation, not everyone in the Organisation!
                otable = s3db.org_organisation
                ottable = s3db.org_organisation_tag
                query = (otable.pe_id == pe_id) & \
                        (ottable.organisation_id == otable.id) & \
                        (ottable.tag == "duty")
                duty = db(query).select(ottable.value,
                                        limitby = (0, 1)
                                        ).first()
                if duty:
                    current.msg.send_sms_via_api(duty.value,
                                                 message)
            else:
                task_notification = settings.get_event_task_notification()
                if task_notification:
                    current.msg.send_by_pe_id(pe_id,
                                              subject = "%s: Task assigned to you" % settings.get_system_name_short(),
                                              message = message,
                                              contact_method = task_notification)

    # -------------------------------------------------------------------------
    def customise_project_task_resource(r, tablename):

        s3db = current.s3db

        f = s3db.project_task.source
        f.readable = f.writable = False

        s3db.configure(tablename,
                       # No need to see time log: KISS
                       crud_form = None,
                       # NB We deliberatly over-ride the default one
                       create_onaccept = project_task_onaccept,
                       # In event_ActionPlan()
                       #list_fields = ["priority",
                       #               "name",
                       #               "pe_id",
                       #               "status_id",
                       #               "date_due",
                       #               ],
                       update_onaccept = lambda form:
                                            project_task_onaccept(form, create=False),
                       )

    settings.customise_project_task_resource = customise_project_task_resource

# END =========================================================================