# -*- coding: utf-8 -*-
#!/usr/bin/env python
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000-2007  Donald N. Allingham
# Copyright (C) 2007       Johan Gonqvist <johan.gronqvist@gmail.com>
# Copyright (C) 2007-2009  Gary Burton <gary.burton@zen.co.uk>
# Copyright (C) 2007-2009  Stephane Charette <stephanecharette@gmail.com>
# Copyright (C) 2008-2009  Brian G. Matherly
# Copyright (C) 2008       Jason M. Simanek <jason@bohemianalps.com>
# Copyright (C) 2008-2011  Rob G. Healey <robhealey1@gmail.com>
# Copyright (C) 2010       Doug Blank <doug.blank@gmail.com>
# Copyright (C) 2010       Jakim Friant
# Copyright (C) 2010-      Serge Noiraud
# Copyright (C) 2011       Tim G L Lyons
# Copyright (C) 2013       Benny Malengier
# Copyright (C) 2016       Allen Crider
#
# This program 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.
#
# This program 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 this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#

"""
Narrative Web Page generator.

Classe:
    PlacePage - Place index page and individual Place pages
"""
#------------------------------------------------
# python modules
#------------------------------------------------
from collections import defaultdict
from decimal import getcontext
import logging

#------------------------------------------------
# Gramps module
#------------------------------------------------
from gramps.gen.const import GRAMPS_LOCALE as glocale
from gramps.gen.lib import (PlaceType, Place)
from gramps.gen.plug.report import Bibliography
from gramps.plugins.lib.libhtml import Html
from gramps.gen.utils.place import conv_lat_lon
from gramps.gen.utils.location import get_main_location

#------------------------------------------------
# specific narrative web import
#------------------------------------------------
from gramps.plugins.webreport.basepage import BasePage
from gramps.plugins.webreport.common import (get_first_letters, first_letter,
                                             alphabet_navigation, GOOGLE_MAPS,
                                             primary_difference, _KEYPLACE,
                                             get_index_letter, FULLCLEAR,
                                             MARKER_PATH, OSM_MARKERS, MARKERS,
                                             html_escape, sort_places)

_ = glocale.translation.sgettext
LOG = logging.getLogger(".NarrativeWeb")
getcontext().prec = 8

######################################################
#                                                    #
#                    Place Pages                     #
#                                                    #
######################################################
class PlacePages(BasePage):
    """
    This class is responsible for displaying information about the 'Person'
    database objects. It displays this information under the 'Events'
    tab. It is told by the 'add_instances' call which 'Person's to display,
    and remembers the list of persons. A single call to 'display_pages'
    displays both the Event List (Index) page and all the Event
    pages.

    The base class 'BasePage' is initialised once for each page that is
    displayed.
    """
    def __init__(self, report):
        """
        @param: report -- The instance of the main report class for
                          this report
        """
        BasePage.__init__(self, report, title="")
        self.place_dict = defaultdict(set)
        self.placemappages = None
        self.mapservice = None
        self.person = None
        self.familymappages = None
        self.googlemapkey = None

        # Place needs to display coordinates?
        self.display_coordinates = report.options["coordinates"]

    def display_pages(self, title):
        """
        Generate and output the pages under the Place tab, namely the place
        index and the individual place pages.

        @param: title -- Is the title of the web page
        """
        LOG.debug("obj_dict[Place]")
        for item in self.report.obj_dict[Place].items():
            LOG.debug("    %s", str(item))
        message = _("Creating place pages")
        with self.r_user.progress(_("Narrated Web Site Report"), message,
                                  len(self.report.obj_dict[Place]) + 1
                                 ) as step:
            index = 1
            for place_handle in self.report.obj_dict[Place]:
                step()
                index += 1
                self.placepage(self.report, title, place_handle)
            step()
            self.placelistpage(self.report, title,
                               self.report.obj_dict[Place].keys())

    def placelistpage(self, report, title, place_handles):
        """
        Create a place index

        @param: report        -- The instance of the main report class for
                                 this report
        @param: title         -- Is the title of the web page
        @param: place_handles -- The handle for the place to add
        """
        BasePage.__init__(self, report, title)

        output_file, sio = self.report.create_file("places")
        result = self.write_header(self._("Places"))
        placelistpage, dummy_head, dummy_body, outerwrapper = result
        ldatec = 0
        prev_letter = " "

        # begin places division
        with Html("div", class_="content", id="Places") as placelist:
            outerwrapper += placelist

            # place list page message
            msg = self._("This page contains an index of all the places in the "
                         "database, sorted by their title. "
                         "Clicking on a place&#8217;s "
                         "title will take you to that place&#8217;s page.")
            placelist += Html("p", msg, id="description")

            # begin alphabet navigation
            index_list = get_first_letters(self.r_db, place_handles,
                                           _KEYPLACE, rlocale=self.rlocale)
            alpha_nav = alphabet_navigation(index_list, self.rlocale)
            if alpha_nav is not None:
                placelist += alpha_nav

            # begin places table and table head
            with Html("table",
                      class_="infolist primobjlist placelist") as table:
                placelist += table

                # begin table head
                thead = Html("thead")
                table += thead

                trow = Html("tr")
                thead += trow

                if self.display_coordinates:
                    trow.extend(
                        Html("th", label, class_=colclass, inline=True)
                        for (label, colclass) in [
                            [self._("Letter"), "ColumnLetter"],
                            [self._("Place Name | Name"), "ColumnName"],
                            [self._("State/ Province"), "ColumnState"],
                            [self._("Country"), "ColumnCountry"],
                            [self._("Latitude"), "ColumnLatitude"],
                            [self._("Longitude"), "ColumnLongitude"]
                        ]
                    )
                else:
                    trow.extend(
                        Html("th", label, class_=colclass, inline=True)
                        for (label, colclass) in [
                            [self._("Letter"), "ColumnLetter"],
                            [self._("Place Name | Name"), "ColumnName"],
                            [self._("State/ Province"), "ColumnState"],
                            [self._("Country"), "ColumnCountry"]
                        ]
                    )

                handle_list = sort_places(self.r_db, place_handles,
                                          self.rlocale)
                first = True

                # begin table body
                tbody = Html("tbody")
                table += tbody

                for (dummy_pname, place_handle) in handle_list:
                    place = self.r_db.get_place_from_handle(place_handle)
                    if place:
                        if place.get_change_time() > ldatec:
                            ldatec = place.get_change_time()
                        plc_title = self.report.obj_dict[Place][place_handle][1]
                        main_location = get_main_location(self.r_db, place)

                        if plc_title and plc_title != " ":
                            letter = get_index_letter(first_letter(plc_title),
                                                      index_list,
                                                      self.rlocale)
                        else:
                            letter = '&nbsp;'

                        trow = Html("tr")
                        tbody += trow

                        tcell = Html("td", class_="ColumnLetter", inline=True)
                        trow += tcell
                        if first or primary_difference(letter, prev_letter,
                                                       self.rlocale):
                            first = False
                            prev_letter = letter
                            trow.attr = 'class = "BeginLetter"'

                            ttle = self._("Places beginning "
                                          "with letter %s") % letter
                            tcell += Html("a", letter, name=letter, title=ttle)
                        else:
                            tcell += "&nbsp;"

                        trow += Html("td",
                                     self.place_link(
                                         place.get_handle(),
                                         plc_title, place.get_gramps_id()),
                                     class_="ColumnName")

                        trow.extend(
                            Html("td", data or "&nbsp;", class_=colclass,
                                 inline=True)
                            for (colclass, data) in [
                                ["ColumnState",
                                 main_location.get(PlaceType.STATE, '')],
                                ["ColumnCountry",
                                 main_location.get(PlaceType.COUNTRY, '')]
                            ]
                        )

                        if self.display_coordinates:
                            tcell1 = Html("td", class_="ColumnLatitude",
                                          inline=True)
                            tcell2 = Html("td", class_="ColumnLongitude",
                                          inline=True)
                            trow += (tcell1, tcell2)

                            if place.lat and place.long:
                                latitude, longitude = conv_lat_lon(place.lat,
                                                                   place.long,
                                                                   "DEG")
                                tcell1 += latitude
                                tcell2 += longitude
                            else:
                                tcell1 += '&nbsp;'
                                tcell2 += '&nbsp;'

        # add clearline for proper styling
        # add footer section
        footer = self.write_footer(ldatec)
        outerwrapper += (FULLCLEAR, footer)

        # send page out for processing
        # and close the file
        self.xhtml_writer(placelistpage, output_file, sio, ldatec)

    def placepage(self, report, title, place_handle):
        """
        Create a place page

        @param: report            -- The instance of the main report class for
                                     this report
        @param: title             -- Is the title of the web page
        @param: place_handle -- The handle for the place to add
        """
        place = report.database.get_place_from_handle(place_handle)
        if not place:
            return
        BasePage.__init__(self, report, title, place.get_gramps_id())
        self.bibli = Bibliography()
        place_name = self.report.obj_dict[Place][place_handle][1]
        ldatec = place.get_change_time()

        output_file, sio = self.report.create_file(place_handle, "plc")
        self.uplink = True
        self.page_title = place_name
        placepage, head, body, outerwrapper = self.write_header(_("Places"))

        self.placemappages = self.report.options['placemappages']
        self.mapservice = self.report.options['mapservice']
        self.googlemapkey = self.report.options['googlemapkey']

        # begin PlaceDetail Division
        with Html("div", class_="content", id="PlaceDetail") as placedetail:
            outerwrapper += placedetail

            if self.create_media:
                media_list = place.get_media_list()
                thumbnail = self.disp_first_img_as_thumbnail(media_list,
                                                             place)
                if thumbnail is not None:
                    placedetail += thumbnail

            # add section title
            placedetail += Html("h3",
                                html_escape(place_name),
                                inline=True)

            # begin summaryarea division and places table
            with Html("div", id='summaryarea') as summaryarea:
                placedetail += summaryarea

                with Html("table", class_="infolist place") as table:
                    summaryarea += table

                    # list the place fields
                    self.dump_place(place, table)

            # place gallery
            if self.create_media:
                placegallery = self.disp_add_img_as_gallery(media_list, place)
                if placegallery is not None:
                    placedetail += placegallery

            # place notes
            notelist = self.display_note_list(place.get_note_list())
            if notelist is not None:
                placedetail += notelist

            # place urls
            urllinks = self.display_url_list(place.get_url_list())
            if urllinks is not None:
                placedetail += urllinks

            # add place map here
            # Link to Gramps marker
            fname = "/".join(['images', 'marker.png'])
            marker_path = self.report.build_url_image("marker.png",
                                                      "images", self.uplink)

            if self.placemappages:
                if place and (place.lat and place.long):
                    latitude, longitude = conv_lat_lon(place.get_latitude(),
                                                       place.get_longitude(),
                                                       "D.D8")
                    placetitle = place_name

                    # add narrative-maps CSS...
                    fname = "/".join(["css", "narrative-maps.css"])
                    url = self.report.build_url_fname(fname, None, self.uplink)
                    head += Html("link", href=url, type="text/css",
                                 media="screen", rel="stylesheet")

                    # add MapService specific javascript code
                    src_js = GOOGLE_MAPS + "api/js?sensor=false"
                    if self.mapservice == "Google":
                        if self.googlemapkey:
                            src_js += "&key=" + self.googlemapkey
                        head += Html("script", type="text/javascript",
                                     src=src_js, inline=True)
                    else:
                        url = self.secure_mode
                        url += ("maxcdn.bootstrapcdn.com/bootstrap/3.3.7/"
                                "css/bootstrap.min.css")
                        head += Html("link", href=url, type="text/javascript",
                                     rel="stylesheet")
                        src_js = self.secure_mode
                        src_js += ("ajax.googleapis.com/ajax/libs/jquery/1.9.1/"
                                   "jquery.min.js")
                        head += Html("script", type="text/javascript",
                                     src=src_js, inline=True)
                        src_js = "https://openlayers.org/en/latest/build/ol.js"
                        head += Html("script", type="text/javascript",
                                     src=src_js, inline=True)
                        url = "https://openlayers.org/en/latest/css/ol.css"
                        head += Html("link", href=url, type="text/javascript",
                                     rel="stylesheet")
                        src_js = self.secure_mode
                        src_js += ("maxcdn.bootstrapcdn.com/bootstrap/3.3.7/"
                                   "js/bootstrap.min.js")
                        head += Html("script", type="text/javascript",
                                     src=src_js, inline=True)

                    # section title
                    placedetail += Html("h4", self._("Place Map"), inline=True)

                    # begin map_canvas division
                    with Html("div", id="map_canvas", inline=True) as canvas:
                        placedetail += canvas

                        # Begin inline javascript code because jsc is a
                        # docstring, it does NOT have to be properly indented
                        if self.mapservice == "Google":
                            with Html("script", type="text/javascript",
                                      indent=False) as jsc:
                                head += jsc

                                # Google adds Latitude/ Longitude to its maps...
                                plce = placetitle.replace("'", "\\'")
                                jsc += MARKER_PATH % marker_path
                                jsc += MARKERS % ([[plce,
                                                    latitude,
                                                    longitude,
                                                    1]],
                                                  latitude, longitude,
                                                  10)

                        else:
                            # OpenStreetMap (OSM) adds Longitude/ Latitude
                            # to its maps, and needs a country code in
                            # lowercase letters...
                            with Html("script", type="text/javascript") as jsc:
                                canvas += jsc
                                #param1 = xml_lang()[3:5].lower()
                                jsc += MARKER_PATH % marker_path
                                jsc += OSM_MARKERS % ([[float(longitude),
                                                        float(latitude),
                                                        placetitle]],
                                                      longitude, latitude, 10)

            # add javascript function call to body element
            body.attr += ' onload = "initialize();" '

            # add div for popups.
            with Html("div", id="popup", inline=True) as popup:
                placedetail += popup

            # source references
            srcrefs = self.display_ind_sources(place)
            if srcrefs is not None:
                placedetail += srcrefs

            # References list
            ref_list = self.display_bkref_list(Place, place_handle)
            if ref_list is not None:
                placedetail += ref_list

        # add clearline for proper styling
        # add footer section
        footer = self.write_footer(ldatec)
        outerwrapper += (FULLCLEAR, footer)

        # send page out for processing
        # and close the file
        self.xhtml_writer(placepage, output_file, sio, ldatec)
