package com.unciv.ui

import com.unciv.ui.utils.AutoScrollPane as ScrollPane
import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.scenes.scene2d.Actor
import com.badlogic.gdx.scenes.scene2d.Group
import com.badlogic.gdx.scenes.scene2d.Touchable
import com.badlogic.gdx.scenes.scene2d.ui.*
import com.badlogic.gdx.utils.Align
import com.unciv.UncivGame
import com.unciv.logic.HexMath
import com.unciv.logic.city.CityInfo
import com.unciv.logic.civilization.CivilizationInfo
import com.unciv.logic.civilization.diplomacy.DiplomaticStatus
import com.unciv.logic.trade.Trade
import com.unciv.logic.trade.TradeOffersList
import com.unciv.models.ruleset.tile.ResourceType
import com.unciv.models.translations.tr
import com.unciv.ui.cityscreen.CityScreen
import com.unciv.ui.pickerscreens.PromotionPickerScreen
import com.unciv.ui.utils.*
import com.unciv.Constants
import java.text.DecimalFormat
import kotlin.math.*

class EmpireOverviewScreen(private val viewingPlayer:CivilizationInfo, private val defaultPage: String = "Cities") : CameraStageBaseScreen(){
    private val topTable = Table().apply { defaults().pad(10f) }
    private val centerTable = Table().apply {  defaults().pad(20f) }

    init {
        onBackButtonClicked { UncivGame.Current.setWorldScreen() }
        val clicks = HashMap<String,() -> Unit>()

        val closeButton = Constants.close.toTextButton()
        closeButton.onClick { UncivGame.Current.setWorldScreen() }
        closeButton.y = stage.height - closeButton.height - 5
        topTable.add(closeButton)

        val setCityInfoButton = "Cities".toTextButton()
        val setCities = {
            centerTable.clear()
            centerTable.add(getCityInfoTable())
            centerTable.pack()
        }
        clicks["Cities"] = setCities
        setCityInfoButton.onClick(setCities)
        topTable.add(setCityInfoButton)

        val setStatsInfoButton = "Stats".toTextButton()
        val setStats = {
            game.settings.addCompletedTutorialTask("See your stats breakdown")
            centerTable.clear()
            centerTable.add(ScrollPane(Table().apply {
                defaults().pad(40f)
                add(getHappinessTable()).top()
                add(getGoldTable()).top()
                add(getScienceTable()).top()
                add(getGreatPeopleTable()).top()
            }))
            centerTable.pack()
        }
        clicks["Stats"] = setStats
        setStatsInfoButton.onClick(setStats)
        topTable.add(setStatsInfoButton)

        val setCurrentTradesButton = "Trades".toTextButton()
        setCurrentTradesButton.onClick {
            centerTable.clear()
            centerTable.add(ScrollPane(getTradesTable())).height(stage.height * 0.8f) // so it doesn't cover the navigation buttons
            centerTable.pack()
        }
        topTable.add(setCurrentTradesButton)
        if (viewingPlayer.diplomacy.values.all { it.trades.isEmpty() })
            setCurrentTradesButton.disable()

        val setUnitsButton = "Units".toTextButton()
        setUnitsButton.onClick {
            centerTable.clear()
            centerTable.add(ScrollPane(getUnitTable()).apply { setOverscroll(false,false) }).height(stage.height * 0.8f)
            centerTable.pack()
        }
        topTable.add(setUnitsButton)


        val setDiplomacyButton = "Diplomacy".toTextButton()
        setDiplomacyButton.onClick {
            centerTable.clear()
            centerTable.add(getDiplomacyGroup()).height(stage.height * 0.8f)
            centerTable.pack()
        }
        topTable.add(setDiplomacyButton)

        val setResourcesButton = "Resources".toTextButton()
        val setResources = {
            centerTable.clear()
            centerTable.add(ScrollPane(getResourcesTable())).size(stage.width * 0.8f, stage.height * 0.8f)
            centerTable.pack()
        }
        clicks["Resources"] = setResources
        setResourcesButton.onClick(setResources)
        topTable.add(setResourcesButton)
        if (viewingPlayer.detailedCivResources.isEmpty())
            setResourcesButton.disable()

        topTable.pack()

        clicks[defaultPage]?.invoke()

        val table = Table()
        table.add(topTable).row()
        table.add(centerTable).expand().row()
        table.setFillParent(true)
        stage.addActor(table)
    }

    private fun getTradesTable(): Table {
        val tradesTable = Table().apply { defaults().pad(10f) }
        val diplomacies = viewingPlayer.diplomacy.values.filter { it.trades.isNotEmpty() }
                .sortedWith(Comparator { d0, d1 ->
                    val d0offers = d0.trades.first().ourOffers
                    val d1offers = d1.trades.first().ourOffers
                    val d0max = if (d0offers.isEmpty()) 0 else d0offers.maxBy { it.duration }!!.duration
                    val d1max = if (d1offers.isEmpty()) 0 else d1offers.maxBy { it.duration }!!.duration
                    when {
                        d0max > d1max -> 1
                        d0max == d1max -> 0
                        else -> -1
                    }
                })
        for(diplomacy in diplomacies) {
            for (trade in diplomacy.trades)
                tradesTable.add(createTradeTable(trade, diplomacy.otherCiv())).row()
        }

        return tradesTable
    }

    private fun createTradeTable(trade: Trade, otherCiv:CivilizationInfo): Table {
        val generalTable = Table(skin)
        generalTable.add(createOffersTable(viewingPlayer,trade.ourOffers, trade.theirOffers.size)).fillY()
        generalTable.add(createOffersTable(otherCiv, trade.theirOffers, trade.ourOffers.size)).fillY()
        return generalTable
    }

    private fun createOffersTable(civ: CivilizationInfo, offersList: TradeOffersList, numberOfOtherSidesOffers: Int): Table {
        val table = Table()
        table.defaults().pad(10f)
        table.background = ImageGetter.getBackground(civ.nation.getOuterColor())
        table.add(civ.civName.toLabel(civ.nation.getInnerColor())).row()
        table.addSeparator()
        for(offer in offersList){
            var offerText = offer.getOfferText()
            if(!offerText.contains("\n")) offerText+="\n"
            table.add(offerText.toLabel(civ.nation.getInnerColor())).row()
        }
        for(i in 1..numberOfOtherSidesOffers - offersList.size)
            table.add("\n".toLabel()).row() // we want both sides of the general table to have the same number of rows
        return table
    }


    private fun getHappinessTable(): Table {
        val happinessTable = Table(skin)
        happinessTable.defaults().pad(5f)
        val happinessHeader = Table(skin)
        happinessHeader.add(ImageGetter.getStatIcon("Happiness")).pad(5f,0f,5f,12f).size(20f)
        happinessHeader.add("Happiness".toLabel(fontSize = 24)).padTop(5f)
        happinessTable.add(happinessHeader).colspan(2).row()
        happinessTable.addSeparator()

        val happinessBreakdown = viewingPlayer.stats().getHappinessBreakdown()

        for (entry in happinessBreakdown.filterNot { it.value.roundToInt()==0 }) {
            happinessTable.add(entry.key.tr())
            happinessTable.add(entry.value.roundToInt().toString()).right().row()
        }
        happinessTable.add("Total".tr())
        happinessTable.add(happinessBreakdown.values.sum().roundToInt().toString()).right()
        happinessTable.pack()
        return happinessTable
    }

    private fun getGoldTable(): Table {
        val goldTable = Table(skin)
        goldTable.defaults().pad(5f)
        val goldHeader = Table(skin)
        goldHeader.add(ImageGetter.getStatIcon("Gold")).pad(5f,0f,5f,12f).size(20f)
        goldHeader.add("Gold".toLabel(fontSize = 24)).padTop(5f)
        goldTable.add(goldHeader).colspan(2).row()
        goldTable.addSeparator()
        var total=0f
        for (entry in viewingPlayer.stats().getStatMapForNextTurn()) {
            if(entry.value.gold==0f) continue
            goldTable.add(entry.key.tr())
            goldTable.add(entry.value.gold.roundToInt().toString()).right().row()
            total += entry.value.gold
        }
        goldTable.add("Total".tr())
        goldTable.add(total.roundToInt().toString()).right()
        goldTable.pack()
        return goldTable
    }


    private fun getScienceTable(): Table {
        val scienceTable = Table(skin)
        scienceTable.defaults().pad(5f)
        val scienceHeader = Table(skin)
        scienceHeader.add(ImageGetter.getStatIcon("Science")).pad(5f,0f,5f,12f).size(20f)
        scienceHeader.add("Science".toLabel(fontSize = 24)).padTop(5f)
        scienceTable.add(scienceHeader).colspan(2).row()
        scienceTable.addSeparator()
        val scienceStats = viewingPlayer.stats().getStatMapForNextTurn()
                .filter { it.value.science!=0f }
        for (entry in scienceStats) {
            scienceTable.add(entry.key.tr())
            scienceTable.add(entry.value.science.roundToInt().toString()).right().row()
        }
        scienceTable.add("Total".tr())
        scienceTable.add(scienceStats.values.map { it.science }.sum().roundToInt().toString()).right()
        scienceTable.pack()
        return scienceTable
    }


    private fun getGreatPeopleTable(): Table {
        val greatPeopleTable = Table(skin)

        val greatPersonPoints = viewingPlayer.greatPeople.greatPersonPoints.toHashMap()
        val greatPersonPointsPerTurn = viewingPlayer.getGreatPersonPointsForNextTurn().toHashMap()
        val pointsToGreatPerson = viewingPlayer.greatPeople.pointsForNextGreatPerson

        greatPeopleTable.defaults().pad(5f)
        val greatPeopleHeader = Table(skin)
        val greatPeopleIcon = ImageGetter.getStatIcon("Specialist")
        greatPeopleIcon.color = Color.ROYAL
        greatPeopleHeader.add(greatPeopleIcon).padRight(12f).size(30f)
        greatPeopleHeader.add("Great person points".toLabel(fontSize = 24)).padTop(5f)
        greatPeopleTable.add(greatPeopleHeader).colspan(3).row()
        greatPeopleTable.addSeparator()
        greatPeopleTable.add()
        greatPeopleTable.add("Current points".tr())
        greatPeopleTable.add("Points per turn".tr()).row()

        val mapping = viewingPlayer.greatPeople.statToGreatPersonMapping
        for(entry in mapping){
            greatPeopleTable.add(entry.value.tr())
            greatPeopleTable.add(greatPersonPoints[entry.key]!!.toInt().toString()+"/"+pointsToGreatPerson)
            greatPeopleTable.add(greatPersonPointsPerTurn[entry.key]!!.toInt().toString()).row()
        }
        val pointsForGreatGeneral = viewingPlayer.greatPeople.greatGeneralPoints.toString()
        val pointsForNextGreatGeneral = viewingPlayer.greatPeople.pointsForNextGreatGeneral.toString()
        greatPeopleTable.add("Great General".tr())
        greatPeopleTable.add("$pointsForGreatGeneral/$pointsForNextGreatGeneral").row()
        greatPeopleTable.pack()
        return greatPeopleTable
    }



    private fun getCityInfoTable(): Table {
        val iconSize = 50f//if you set this too low, there is a chance that the tables will be misaligned
        val padding = 5f
        var sortedBy = "City"

        val cityInfoTableDetails = Table(skin)
        cityInfoTableDetails.defaults().pad(padding).minWidth(iconSize).align(Align.left)//we need the min width so we can align the different tables

        fun sortOnClick(iconName: String) {
            val descending = sortedBy == iconName
            sortedBy = iconName
            // sort the table: clear and fill with sorted data
            cityInfoTableDetails.clear()
            fillCitiesTable(cityInfoTableDetails, iconName, descending)
            // reset to return back for ascending next time
            if (descending) sortedBy = ""
        }

        val cityInfoTableIcons = Table(skin)
        cityInfoTableIcons.defaults().pad(padding).align(Align.center)

        cityInfoTableIcons.add("Cities".toLabel(fontSize = 24)).colspan(8).align(Align.center).row()

        val citySortIcon = ImageGetter.getUnitIcon("Settler").surroundWithCircle(iconSize)
        citySortIcon.onClick { sortOnClick("City") }
        cityInfoTableIcons.add(citySortIcon).align(Align.left)

        val columnsNames = arrayListOf("Population", "Food", "Gold", "Science", "Production", "Culture", "Happiness")
        for (name in columnsNames) {
            val icon = ImageGetter.getStatIcon(name)
            icon.onClick { sortOnClick(name) }
            cityInfoTableIcons.add(icon).size(iconSize)
        }
        cityInfoTableIcons.pack()

        fillCitiesTable(cityInfoTableDetails, "City", false)

        val cityInfoScrollPane = ScrollPane(cityInfoTableDetails)
        cityInfoScrollPane.pack()
        cityInfoScrollPane.setOverscroll(false, false)//I think it feels better with no overscroll

        val cityInfoTableTotal = Table(skin)
        cityInfoTableTotal.defaults().pad(padding).minWidth(iconSize)//we need the min width so we can align the different tables

        cityInfoTableTotal.add("Total".tr())
        cityInfoTableTotal.add(viewingPlayer.cities.sumBy { it.population.population }.toString()).actor!!.setAlignment(Align.center)
        cityInfoTableTotal.add()//an intended empty space
        cityInfoTableTotal.add(viewingPlayer.cities.sumBy { it.cityStats.currentCityStats.gold.toInt() }.toString()).actor!!.setAlignment(Align.center)
        cityInfoTableTotal.add(viewingPlayer.cities.sumBy { it.cityStats.currentCityStats.science.toInt() }.toString()).actor!!.setAlignment(Align.center)
        cityInfoTableTotal.add()//an intended empty space
        cityInfoTableTotal.add(viewingPlayer.cities.sumBy { it.cityStats.currentCityStats.culture.toInt() }.toString()).actor!!.setAlignment(Align.center)
        cityInfoTableTotal.add(viewingPlayer.cities.sumBy {  it.cityStats.currentCityStats.happiness.toInt() }.toString()).actor!!.setAlignment(Align.center)

        cityInfoTableTotal.pack()

        val table = Table(skin)
        //since the names of the cities are on the left, and the length of the names varies
        //we align every row to the right, coz we set the size of the other(number) cells to the image size
        //and thus, we can guarantee that the tables will be aligned
        table.defaults().pad(padding).align(Align.right)

        // place the button for sorting by city name on top of the cities names
        citySortIcon.width = max(iconSize, cityInfoTableDetails.width - (iconSize+padding) * 8)

        table.add(cityInfoTableIcons).row()
        table.add(cityInfoScrollPane).width(cityInfoTableDetails.width).row()
        table.add(cityInfoTableTotal)
        table.pack()

        return table
    }

    private fun fillCitiesTable(citiesTable: Table, sortType: String, descending: Boolean) {

        val sorter = Comparator {city2, city1 : CityInfo -> when (sortType) {
            "Population" -> city1.population.population - city2.population.population
            "Food" ->       (city1.cityStats.currentCityStats.food - city2.cityStats.currentCityStats.food).toInt()
            "Gold" ->       (city1.cityStats.currentCityStats.gold - city2.cityStats.currentCityStats.gold).toInt()
            "Science" ->    (city1.cityStats.currentCityStats.science - city2.cityStats.currentCityStats.science).toInt()
            "Production" -> (city1.cityStats.currentCityStats.production - city2.cityStats.currentCityStats.production).toInt()
            "Culture" ->    (city1.cityStats.currentCityStats.culture - city2.cityStats.currentCityStats.culture).toInt()
            "Happiness" ->  (city1.cityStats.currentCityStats.happiness - city2.cityStats.currentCityStats.happiness).toInt()
            else ->         city2.name.compareTo(city1.name)
        } }

        var cityList = viewingPlayer.cities.sortedWith(sorter)

        if (descending)
            cityList = cityList.reversed()

        for (city in cityList) {
            val button = Button(city.name.toLabel(), skin)
            button.onClick {
                UncivGame.Current.setScreen(CityScreen(city))
            }
            citiesTable.add(button)
            citiesTable.add(city.cityConstructions.getCityProductionTextForCityButton()).actor!!.setAlignment(Align.left)
            citiesTable.add(city.population.population.toString()).actor!!.setAlignment(Align.center)
            citiesTable.add(city.cityStats.currentCityStats.food.roundToInt().toString()).actor!!.setAlignment(Align.center)
            citiesTable.add(city.cityStats.currentCityStats.gold.roundToInt().toString()).actor!!.setAlignment(Align.center)
            citiesTable.add(city.cityStats.currentCityStats.science.roundToInt().toString()).actor!!.setAlignment(Align.center)
            citiesTable.add(city.cityStats.currentCityStats.production.roundToInt().toString()).actor!!.setAlignment(Align.center)
            citiesTable.add(city.cityStats.currentCityStats.culture.roundToInt().toString()).actor!!.setAlignment(Align.center)
            citiesTable.add(city.cityStats.currentCityStats.happiness.roundToInt().toString()).actor!!.setAlignment(Align.center)
            citiesTable.row()
        }
        citiesTable.pack()
    }

    private fun getUnitTable(): Table {
        val table=Table(skin).apply { defaults().pad(5f) }
        table.add("Name".tr())
        table.add("Action".tr())
        table.add("Strength".tr())
        table.add("Ranged strength".tr())
        table.add("Movement".tr())
        table.add("Closest city".tr())
        table.add("Promotions".tr())
        table.add("Health".tr())
        table.row()
        table.addSeparator()

        for(unit in viewingPlayer.getCivUnits().sortedWith(compareBy({it.name},{!it.due},
                {it.currentMovement<0.1f},{abs(it.currentTile.position.x)+abs(it.currentTile.position.y)}))) {
            val baseUnit = unit.baseUnit()
            val button = TextButton(unit.name.tr(), skin)
            button.onClick {
                UncivGame.Current.setWorldScreen()
                UncivGame.Current.worldScreen.mapHolder.setCenterPosition(unit.currentTile.position)
            }
            table.add(button).left()
            val mapUnitAction = unit.mapUnitAction
            if (mapUnitAction != null) table.add(if(mapUnitAction.name().startsWith("Fortify")) "Fortify".tr() else mapUnitAction.name().tr()) else table.add()
            if(baseUnit.strength>0) table.add(baseUnit.strength.toString()) else table.add()
            if(baseUnit.rangedStrength>0) table.add(baseUnit.rangedStrength.toString()) else table.add()
            table.add(DecimalFormat("0.#").format(unit.currentMovement)+"/"+unit.getMaxMovement())
            val closestCity = unit.getTile().getTilesInDistance(3).firstOrNull{it.isCityCenter()}
            if (closestCity!=null) table.add(closestCity.getCity()!!.name.tr()) else table.add()
            val promotionsTable = Table()
            val promotionsForUnit = unit.civInfo.gameInfo.ruleSet.unitPromotions.values.filter { unit.promotions.promotions.contains(it.name) }     // force same sorting as on picker (.sorted() would be simpler code, but...)
            for(promotion in promotionsForUnit)
                promotionsTable.add(ImageGetter.getPromotionIcon(promotion.name))
            if (unit.promotions.canBePromoted()) promotionsTable.add(ImageGetter.getImage("OtherIcons/Star").apply { color= Color.GOLDENROD }).size(24f).padLeft(8f)
            if (unit.canUpgrade()) promotionsTable.add(ImageGetter.getUnitIcon(baseUnit.upgradesTo!!, Color.GREEN)).size(28f).padLeft(8f)
            promotionsTable.onClick {
                if (unit.promotions.canBePromoted() || unit.promotions.promotions.isNotEmpty()) {
                    UncivGame.Current.setScreen(PromotionPickerScreen(unit))
                }
            }
            table.add(promotionsTable)
            if (unit.health < 100) table.add(unit.health.toString()) else table.add()
            table.row()
        }
        table.pack()
        return table
    }


    private fun playerKnows(civ:CivilizationInfo) = civ==viewingPlayer ||
            viewingPlayer.diplomacy.containsKey(civ.civName)

    private fun getDiplomacyGroup(): Group {
        val relevantCivs = viewingPlayer.gameInfo.civilizations.filter { !it.isBarbarian() && !it.isCityState() }
        val freeWidth = stage.width
        val freeHeight = stage.height - topTable.height
        val group = Group()
        group.setSize(freeWidth,freeHeight)
        val civGroups = HashMap<String, Actor>()
        val civLines = HashMap<String, MutableSet<Actor>>()
        for(i in 0..relevantCivs.lastIndex){
            val civ = relevantCivs[i]

            val civGroup = getCivGroup(civ, "", viewingPlayer)

            val vector = HexMath.getVectorForAngle(2 * Math.PI.toFloat() *i / relevantCivs.size)
            civGroup.center(group)
            civGroup.moveBy(vector.x*freeWidth/2.5f, vector.y*freeHeight/2.5f)
            civGroup.touchable = Touchable.enabled
            civGroup.onClick {
                onCivClicked(civLines, civ.civName)
            }

            civGroups[civ.civName]=civGroup
            group.addActor(civGroup)
        }

        for(civ in relevantCivs.filter { playerKnows(it) && !it.isDefeated() })
            for(diplomacy in civ.diplomacy.values.
                    filter { !it.otherCiv().isBarbarian() && !it.otherCiv().isCityState()
                            && playerKnows(it.otherCiv()) && !it.otherCiv().isDefeated()}){
                val civGroup = civGroups[civ.civName]!!
                val otherCivGroup = civGroups[diplomacy.otherCivName]!!

                if (!civLines.containsKey(civ.civName))
                    civLines[civ.civName] = mutableSetOf()

                val statusLine = ImageGetter.getLine(civGroup.x+civGroup.width/2,civGroup.y+civGroup.height/2,
                        otherCivGroup.x+otherCivGroup.width/2,otherCivGroup.y+otherCivGroup.height/2,3f)

                // draw a parallel line for additional relationships
                if (diplomacy.hasOpenBorders ||
                        diplomacy.diplomaticStatus == DiplomaticStatus.War ||
                        diplomacy.totalOfScienceDuringRA > 0) {
                    val lineAngle = (statusLine.rotation-90) * Math.PI / 180
                    val shiftX = 4f*cos(lineAngle).toFloat()
                    val shiftY = 4f*sin(lineAngle).toFloat()
                    val secondaryLine = ImageGetter.getLine(civGroup.x+civGroup.width/2+shiftX,civGroup.y+civGroup.height/2+shiftY,
                                otherCivGroup.x+otherCivGroup.width/2+shiftX,otherCivGroup.y+otherCivGroup.height/2+shiftY,2f)

                    secondaryLine.color = when {
                        diplomacy.diplomaticStatus == DiplomaticStatus.War -> Color.RED
                        diplomacy.hasOpenBorders -> Color.CYAN
                        diplomacy.totalOfScienceDuringRA > 0 -> Color.BLUE
                        else -> Color.WHITE
                    }

                    civLines[civ.civName]!!.add(secondaryLine)

                    group.addActor(secondaryLine)
                    secondaryLine.toBack()
                }

                val diplomacyLevel = diplomacy.diplomaticModifiers.values.sum()
                statusLine.color = getColorForDiplomacyLevel(diplomacyLevel)

                civLines[civ.civName]!!.add(statusLine)

                group.addActor(statusLine)
                statusLine.toBack()
            }

        return group
    }

    private fun onCivClicked(civLines: HashMap<String, MutableSet<Actor>>, name: String) {
        // ignore the clicks on "dead" civilizations, and remember the selected one
        val selectedLines = civLines[name] ?: return

        // let's check whether lines of all civs are visible (except selected one)
        var atLeastOneLineVisible = false
        var allAreLinesInvisible = true
        for (lines in civLines.values) {
            // skip the civilization selected by user, and civilizations with no lines
            if (lines == selectedLines || lines.isEmpty()) continue

            val visibility = lines.first().isVisible
            atLeastOneLineVisible = atLeastOneLineVisible || visibility
            allAreLinesInvisible = allAreLinesInvisible && visibility

            // check whether both visible and invisible lines are present
            if (atLeastOneLineVisible && !allAreLinesInvisible) {
                // invert visibility of the selected civ's lines
                selectedLines.forEach{ it.isVisible = !it.isVisible }
                return
            }
        }
        
        if (selectedLines.first().isVisible)
            // invert visibility of all lines except selected one
            civLines.filter{ it.key != name }.forEach{ it.value.forEach{line -> line.isVisible = !line.isVisible} }
        else
            // it happens only when all are visible except selected one
            // invert visibility of the selected civ's lines
            selectedLines.forEach{ it.isVisible = !it.isVisible }
    }

    private fun getColorForDiplomacyLevel(value: Float): Color {

        var amplitude = min(1.0f,abs(value)/80) // 80 = RelationshipLevel.Ally
        val shade = max(0.5f - amplitude, 0.0f)
        amplitude = max(amplitude, 0.5f)

        return Color( if (sign(value) < 0) amplitude else shade,
                      if (sign(value) > 0) amplitude else shade,
                      shade,1.0f)
    }


    private fun getResourcesTable(): Table {
        val resourcesTable=Table().apply { defaults().pad(10f) }
        val resourceDrilldown = viewingPlayer.detailedCivResources

        // First row of table has all the icons
        resourcesTable.add()
        val resources = resourceDrilldown.map { it.resource }
                .filter { it.resourceType!=ResourceType.Bonus }.distinct().sortedBy { it.resourceType }

        var visibleLabel: Label? = null
        for(resource in resources) {
            // Create a group of label and icon for each resource.
            val resourceImage = ImageGetter.getResourceImage(resource.name,50f)
            val resourceLabel = resource.name.toLabel()
            val labelPadding = 10f
            // Using a table here leads to spacing issues
            // due to different label lengths.
            val holder = Group()
            resourceImage.onClick {
                if (visibleLabel != null)
                    visibleLabel!!.setVisible(false)
                resourceLabel.setVisible(true)
                visibleLabel = resourceLabel
            }
            holder.addActor(resourceImage)
            holder.addActor(resourceLabel)
            holder.setSize(resourceImage.getWidth(),
                    resourceImage.getHeight() + resourceLabel.getHeight() + labelPadding)
            // Center-align all labels, but right-align the last couple resources' labels
            // because they may get clipped otherwise. The leftmost label should be fine
            // center-aligned (if there are more than 2 resources), because the left side
            // has more padding.
            val alignFactor = when {
                (resources.indexOf(resource) + 2 >= resources.count()) -> 1
                else -> 2
            }
            resourceLabel.moveBy((resourceImage.getWidth() - resourceLabel.getWidth()) / alignFactor,
                    resourceImage.getHeight() + labelPadding)
            resourceLabel.setVisible(false)
            resourcesTable.add(holder)
        }
        resourcesTable.addSeparator()

        val origins = resourceDrilldown.map { it.origin }.distinct()
        for(origin in origins){
            resourcesTable.add(origin.toLabel())
            for(resource in resources){
                val resourceSupply = resourceDrilldown.firstOrNull { it.resource==resource && it.origin==origin }
                if(resourceSupply==null) resourcesTable.add()
                else resourcesTable.add(resourceSupply.amount.toString().toLabel())
            }
            resourcesTable.row()
        }

        resourcesTable.add("Total".toLabel())
        for(resource in resources){
            val sum = resourceDrilldown.filter { it.resource==resource }.sumBy { it.amount }
            resourcesTable.add(sum.toString().toLabel())
        }

        return resourcesTable
    }

    companion object {
        fun getCivGroup(civ: CivilizationInfo, afterCivNameText:String,currentPlayer:CivilizationInfo): Table {
            val civGroup = Table()

            var labelText = civ.civName.tr()+afterCivNameText
            var labelColor=Color.WHITE
            val backgroundColor:Color

            if (civ.isDefeated()) {
                civGroup.add(ImageGetter.getImage("OtherIcons/DisbandUnit")).size(30f)
                backgroundColor = Color.LIGHT_GRAY
                labelColor = Color.BLACK
            } else if (currentPlayer==civ || UncivGame.Current.viewEntireMapForDebug
                    || currentPlayer.knows(civ) || currentPlayer.isDefeated() || currentPlayer.victoryManager.hasWon()) {
                civGroup.add(ImageGetter.getNationIndicator(civ.nation, 30f))
                backgroundColor = civ.nation.getOuterColor()
                labelColor = civ.nation.getInnerColor()
            } else {
                backgroundColor = Color.DARK_GRAY
                labelText = "???"
            }

            civGroup.background = ImageGetter.getRoundedEdgeTableBackground(backgroundColor)
            val label = labelText.toLabel(labelColor)
            label.setAlignment(Align.center)

            civGroup.add(label).pad(10f)
            civGroup.pack()
            return civGroup
        }
    }
}