# coding: utf-8
"""
Name: japanmap.py

Plot japan map using cartopy.

Usage: This is the module.

Author: Ryosuke Tomita
Date: 2021/09/08
"""
import matplotlib.pyplot as plt
import matplotlib.ticker as mticker
import cartopy.crs as ccrs
import cartopy.feature as cfea
from cartopy.mpl.ticker import LatitudeFormatter, LongitudeFormatter
import numpy as np


class JpMap:
    """Make map near japan."""
    def __init__(self):
        self.fig = plt.figure(figsize=(36, 24), facecolor='w')
        self.ax = self.fig.add_subplot(1, 1, 1,
                                       projection=ccrs.PlateCarree(central_longitude=0.0))

        self.ax.set_global()
        self.ax.coastlines()

        # using axis lat,lon format
        dlon, dlat = 10, 10  # grid line interval.
        xticks = np.arange(-180, 180.1, dlon)
        yticks = np.arange(-90, 90.1, dlat)
        self.ax.set_xticks(xticks, crs=ccrs.PlateCarree())
        self.ax.set_yticks(yticks, crs=ccrs.PlateCarree())
        latfmt = LatitudeFormatter()  # axis = degree
        lonfmt = LongitudeFormatter(
            zero_direction_label=True)  # No NS mark 0 degree
        self.ax.xaxis.set_major_formatter(lonfmt)
        self.ax.yaxis.set_major_formatter(latfmt)
        self.ax.axes.tick_params(labelsize=12)

        # land color,ocean color
        self.ax.add_feature(cfea.LAND, color='#98fb98')
        self.ax.add_feature(cfea.OCEAN, color='#87cefa')

        # grid setting
        grid = self.ax.gridlines(crs=ccrs.PlateCarree(),
                                 draw_labels=False,
                                 linewidth=1,
                                 alpha=0.8,
                                 color='k',)
        grid.xlocator = mticker.FixedLocator(xticks)
        grid.ylocator = mticker.FixedLocator(yticks)

        # chose near japan from the world map
        self.ax.set_xlim(110, 180)
        self.ax.set_ylim(20, 60)

        self.color_list = ['#b22222', '#ffa500', '#ffd700', '#006400',
                      '#3cb371', '#00bfff', '#0000ff', '#9932cc', '#c71585']

        self.plt_cnt = 0

    def plot_data(self, x, y, label):
        """plot location data. plot type is dot."""
        self.ax.plot(y, x, 'bo',
                     label           = label,
                     markersize      = 15,
                     color           =self.color_list[self.plt_cnt],
                     markeredgewidth =1.6,
                     markeredgecolor ='#000000',
                     linestyle       ="solid",)
        self.plt_cnt += 1

    def plot_value(self, x, y, z):
        """plot z value on japan map. x, y are location data. """
        for i in range(len(x)):
            self.ax.plot(y[i], x[i], marker=str(f'${z[i]:.2f}$'), markersize=90, color='k')

    def contour_plot(self, x, y, z):
        """make contour map."""
        plt.rcParams["font.size"] = 30
        X, Y = np.meshgrid(x, y)
        contour = self.ax.contour(X, Y, z, colors="black")
        #contour = self.ax.contour(X, Y, z, 1000,colors="black",vmin=0.8, vmax=1.0)
        self.ax.clabel(contour)

    def shade_plot(self, x, y, z, label):
        """make color map."""
        X, Y = np.meshgrid(x, y)
        shade = self.ax.pcolormesh(X, Y, z, cmap = "rainbow")
        color_bar = plt.colorbar(shade, orientation="vertical")
        color_bar.set_label(label, fontsize=24)

    def vector_plot(self, x, y, u, v, vector_interval, vector_scale):
        """make vector map."""
        def skip_value(array, len_x, len_y, vector_interval):
            skiped_array = [array[i][j] for i in range(len_y) for j in range(len_x) if i%vector_interval == 0 and j % vector_interval == 0]
            return skiped_array

        u_skipped = skip_value(u, len(x), len(y), vector_interval)
        v_skipped = skip_value(v, len(x), len(y), vector_interval)
        x_2d, y_2d = np.meshgrid(x, y)
        x_2d_skipped = skip_value(x_2d, len(x), len(y), vector_interval)
        y_2d_skipped = skip_value(y_2d, len(x), len(y), vector_interval)

        self.ax.quiver(x_2d_skipped, y_2d_skipped, u_skipped, v_skipped, angles='uv',
                       scale_units='xy', scale=vector_scale, headlength=3.5)

    def save_fig(self, outname, title):
        """save figure."""
        self.ax.set_title(title, fontsize=24)
        bar, label = self.ax.get_legend_handles_labels()
        self.ax.legend(bar, label, loc='upper left',borderaxespad=0,
                       bbox_to_anchor=(1.05, 1), fontsize=30)
        self.fig.savefig(outname, bbox_inches="tight", pad_inches=0.5)
        plt.close()
