from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import ee

from .util import TEImage
from te_schemas.schemas import BandInfo


def urban_area(geojson, un_adju, EXECUTION_ID, logger):
    """
    Calculate urban area.
    """

    logger.debug("Entering urban_area function.")

    aoi = ee.Geometry(geojson)

    # Read asset with the time series of urban extent
    urban_series = ee.Image(
        "users/geflanddegradation/toolbox_datasets/urban_series"
    ).int32()

    # Load population data from GPWv4: Gridded Population of the World Version 4, People/km2 (not UN adjusted)
    if un_adju:
        pop_densi = ee.ImageCollection("CIESIN/GPWv4/population-density")
    else:
        pop_densi = ee.ImageCollection("CIESIN/GPWv4/unwpp-adjusted-population-density")

    # the .multiply(100).int32() is to make the rasters integers, with units for density of people/km2 * 100

    # Select population datasets for each year
    pop2000 = (
        pop_densi.filter(ee.Filter.eq("system:index", "2000"))
        .mean()
        .multiply(100)
        .int32()
    )
    pop2005 = (
        pop_densi.filter(ee.Filter.eq("system:index", "2005"))
        .mean()
        .multiply(100)
        .int32()
    )
    pop2010 = (
        pop_densi.filter(ee.Filter.eq("system:index", "2010"))
        .mean()
        .multiply(100)
        .int32()
    )
    pop2015 = (
        pop_densi.filter(ee.Filter.eq("system:index", "2015"))
        .mean()
        .multiply(100)
        .int32()
    )

    # Use urban extent to mask population density data
    urb_pop2000 = pop2000.updateMask(urban_series.eq(1))
    urb_pop2005 = pop2005.updateMask(urban_series.gte(1).And(urban_series.lte(2)))
    urb_pop2010 = pop2010.updateMask(urban_series.gte(1).And(urban_series.lte(3)))
    urb_pop2015 = pop2015.updateMask(urban_series.gte(1).And(urban_series.lte(4)))

    # Compute mean population density per year
    urb_pop2000m = urb_pop2000.reduceRegion(
        reducer=ee.Reducer.mean(), geometry=aoi, scale=30, maxPixels=1e12
    )
    urb_pop2005m = urb_pop2005.reduceRegion(
        reducer=ee.Reducer.mean(), geometry=aoi, scale=30, maxPixels=1e12
    )
    urb_pop2010m = urb_pop2010.reduceRegion(
        reducer=ee.Reducer.mean(), geometry=aoi, scale=30, maxPixels=1e12
    )
    urb_pop2015m = urb_pop2015.reduceRegion(
        reducer=ee.Reducer.mean(), geometry=aoi, scale=30, maxPixels=1e12
    )

    # Compute urban area per year
    pixel_area = urban_series.updateMask(urban_series.eq(1)).multiply(
        ee.Image.pixelArea()
    )

    urb_are2000 = (
        urban_series.updateMask(urban_series.eq(1))
        .multiply(ee.Image.pixelArea())
        .reduceRegion(reducer=ee.Reducer.sum(), geometry=aoi, scale=30, maxPixels=1e12)
    )
    urb_are2005 = (
        urban_series.updateMask(urban_series.gte(1).And(urban_series.lte(2)))
        .multiply(ee.Image.pixelArea())
        .reduceRegion(reducer=ee.Reducer.sum(), geometry=aoi, scale=30, maxPixels=1e12)
    )
    urb_are2010 = (
        urban_series.updateMask(urban_series.gte(1).And(urban_series.lte(3)))
        .multiply(ee.Image.pixelArea())
        .reduceRegion(reducer=ee.Reducer.sum(), geometry=aoi, scale=30, maxPixels=1e12)
    )
    urb_are2015 = (
        urban_series.updateMask(urban_series.gte(1).And(urban_series.lte(4)))
        .multiply(ee.Image.pixelArea())
        .reduceRegion(reducer=ee.Reducer.sum(), geometry=aoi, scale=30, maxPixels=1e12)
    )

    # Make a dictionary to contain results
    result_table = ee.Dictionary(
        {
            "pop_dens2000": urb_pop2000m.get("population-density"),
            "pop_dens2005": urb_pop2005m.get("population-density"),
            "pop_dens2010": urb_pop2010m.get("population-density"),
            "pop_dens2015": urb_pop2015m.get("population-density"),
            "urb_area2000": urb_are2000.get("classification"),
            "urb_area2005": urb_are2005.get("classification"),
            "urb_area2010": urb_are2010.get("classification"),
            "urb_area2015": urb_are2015.get("classification"),
        }
    )

    # # Export the FeatureCollection.
    # Export.table.toDrive({
    #   collection: ee.FeatureCollection([ee.Feature(null,result_table)]),
    #   description: "export_urban_extent_table",
    #   folder: 'sdg1131',
    #   fileFormat: 'CSV'})
    #
    # Export raster
    result_raster = (
        urban_series.addBands(urb_pop2000)
        .addBands(urb_pop2005)
        .addBands(urb_pop2010)
        .addBands(urb_pop2015)
    )

    logger.debug("Setting up output.")
    out = TEImage(
        result_raster.clip(aoi),
        [
            BandInfo(
                "Urban series",
                add_to_map=True,
                metadata={"years": [2000, 2005, 2010, 2015]},
            ),
            BandInfo("Population", metadata={"year": 2000}),
            BandInfo("Population", metadata={"year": 2005}),
            BandInfo("Population", metadata={"year": 2010}),
            BandInfo("Population", add_to_map=True, metadata={"year": 2015}),
        ],
    )

    # out.image = out.image.unmask(-32768).int16()

    return out
