package theorycrafter.ui

import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.defaultMinSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.size
import androidx.compose.material.Icon
import androidx.compose.material.LocalContentAlpha
import androidx.compose.material.LocalContentColor
import androidx.compose.material.icons.automirrored.outlined.*
import androidx.compose.material.icons.outlined.*
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.graphics.DefaultAlpha
import androidx.compose.ui.graphics.painter.BitmapPainter
import androidx.compose.ui.graphics.painter.Painter
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.semantics.Role
import androidx.compose.ui.semantics.SemanticsProperties
import androidx.compose.ui.semantics.role
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import compose.widgets.SingleLineText
import eve.data.EveItemType
import eve.data.EveObjectWithIcon
import eve.data.MarketGroup
import org.jetbrains.compose.resources.DrawableResource
import org.jetbrains.compose.resources.ExperimentalResourceApi
import org.jetbrains.compose.resources.decodeToImageBitmap
import org.jetbrains.compose.resources.vectorResource
import theorycrafter.AnalyticsConsent
import theorycrafter.TheorycrafterContext
import theorycrafter.fitting.Module
import theorycrafter.generated.resources.*
import theorycrafter.utils.thenIf


/**
 * Holds the icons used by the app.
 */
object Icons {


    /**
     * The icon for an EVE item, if it has one.
     */
    @Composable
    fun EveItemType(
        itemType: EveItemType,
        modifier: Modifier = Modifier
    ) {
        if (itemType.hasIcon) {
            EveResourceImage(
                eveObject = itemType,
                contentDescription = itemType.name,
                modifier = modifier
                    .thenIf(itemType.isIconRendering) {
                        clip(TheorycrafterTheme.eveTypeRenderingClip)
                    }
            )
        }
    }


    /**
     * The icon for an EVE market group, if it has one.
     */
    @Composable
    fun MarketGroup(
        marketGroup: MarketGroup,
        modifier: Modifier = Modifier
    ) {
        if (marketGroup.hasIcon) {
            EveResourceImage(
                eveObject = marketGroup,
                modifier = modifier,
                contentDescription = marketGroup.name,
            )
        }
    }


    /**
     * The icon for a "Copy" action.
     */
    @Composable
    fun Copy() {
        Icon(TheorycrafterTheme.iconStyle.ContentCopy)
    }


    /**
     * The icon for a "Copy with options" action.
     */
    @Composable
    fun CopyWithOptions() {
        Icon(vectorResource(Res.drawable.copy_with_options))
    }


    /**
     * The icon for a "Paste" action.
     */
    @Composable
    fun Paste() {
        Icon(TheorycrafterTheme.iconStyle.ContentPaste)
    }


    /**
     * The icon for a "Cut" action.
     */
    @Composable
    fun Cut() {
        Icon(TheorycrafterTheme.iconStyle.ContentCut)
    }


    /**
     * The icon for a "Duplicate" action.
     */
    @Composable
    fun Duplicate() {
        Icon(vectorResource(Res.drawable.duplicate))
    }


    /**
     * The icon for a "Delete" action.
     */
    @Composable
    fun Delete(modifier: Modifier = Modifier) {
        Icon(
            imageVector = vectorResource(Res.drawable.delete),
            modifier = modifier
        )
    }


    /**
     * The icon for an "Edit" action.
     */
    @Composable
    fun Edit(modifier: Modifier = Modifier) {
        Icon(
            imageVector = TheorycrafterTheme.iconStyle.Edit,
            modifier = modifier
        )
    }


    /**
     * The icon for a "Hashtag" action.
     */
    @Composable
    fun Hashtag() {
        Icon(TheorycrafterTheme.iconStyle.Tag)
    }


    /**
     * The icon for a "Share" action.
     */
    @Composable
    fun Share(modifier: Modifier = Modifier) {
        Icon(
            imageVector = TheorycrafterTheme.iconStyle.IosShare,
            modifier = modifier
        )
    }


    /**
     * The icon for an "Open in New" action.
     */
    @Composable
    fun OpenInNew() {
        Icon(TheorycrafterTheme.autoMirroredIconStyle.OpenInNew)
    }


    /**
     * The icon for an "Import from file" action.
     */
    @Composable
    fun ImportFromFile() {
        Icon(TheorycrafterTheme.iconStyle.FileOpen)
    }


    /**
     * The icon for an "Import from Pyfa" action.
     */
    @Composable
    fun ImportFromPyfa() {
        SingleLineText(
            text = "Py",
            style = TextStyle(
                fontSize = 13.sp,
                letterSpacing = (-2).sp,
            ),
            textAlign = TextAlign.Center,
            modifier = Modifier
                .defaultMinSize(24.dp)
                .semantics {
                    role = Role.Image
                    set(SemanticsProperties.Text, emptyList())
                }
        )
    }


    /**
     * The icon for a "Plus One" action.
     */
    @Composable
    fun PlusOne() {
        Icon(vectorResource(Res.drawable.plus_one))
    }


    /**
     * The icon for a "Minus One" action.
     */
    @Composable
    fun MinusOne() {
        Icon(vectorResource(Res.drawable.minus_one))
    }


    /**
     * The icon for an "Add to cargo" action.
     */
    @Composable
    fun AddToCargo() {
        Icon(vectorResource(Res.drawable.add_to_cargo))
    }


    /**
     * The icon for a "Pack for battle" action.
     */
    @Composable
    fun PackForBattle() {
        Icon(vectorResource(Res.drawable.pack_for_battle))
    }


    /**
     * The icon for editing an item's mutation.
     */
    @Composable
    fun EditMutation() {
        Icon(TheorycrafterTheme.iconStyle.ModeEdit)
    }


    /**
     * The icon for reverting an item to its base type.
     */
    @Composable
    fun RevertMutation() {
        Icon(TheorycrafterTheme.autoMirroredIconStyle.Undo)
    }


    /**
     * The icon for setting the spoolup cycles of a module.
     */
    @Composable
    fun SpoolupCycles(modifier: Modifier = Modifier) {
        Icon(
            imageVector = vectorResource(Res.drawable.spoolup_cycles),
            modifier = modifier
        )
    }


    /**
     * The icon for setting the adaptation cycles of a module.
     */
    @Composable
    fun AdaptationCycles(modifier: Modifier = Modifier) {
        SpoolupCycles(modifier)
    }


    /**
     * The icon for enabling all items of some kind.
     */
    @Composable
    fun EnableAll() {
        Icon(TheorycrafterTheme.iconStyle.DoneAll)
    }


    /**
     * The icon for disabling all items of some kind.
     */
    @Composable
    fun DisableAll() {
        Icon(TheorycrafterTheme.iconStyle.RemoveDone)
    }


    /**
     * The icon used to indicate the given module state.
     */
    @Composable
    fun ModuleState(
        state: Module.State,
        modifier: Modifier = Modifier
    ){
        when (state){
            Module.State.OFFLINE -> OfflineItem(modifier)
            Module.State.ONLINE -> OnlineItem(modifier)
            Module.State.ACTIVE -> ActiveItem(modifier)
            Module.State.OVERLOADED -> OverloadedItem(modifier)
        }
    }


    /**
     * The icon used to indicate the given drone group state.
     */
    @Composable
    fun DroneGroupState(
        isActive: Boolean,
        modifier: Modifier = Modifier
    ){
        return if (isActive)
            ActiveItem(modifier)
        else
            OnlineItem(modifier)
    }


    /**
     * The icon used to indicate the given enabled state of some item.
     */
    @Composable
    fun ItemEnabledState(
        enabled: Boolean,
        modifier: Modifier = Modifier
    ) {
        return if (enabled)
            ActiveItem(modifier)
        else
            OfflineItem(modifier)
    }


    /**
     * The icon used to indicate an offline item.
     */
    @Composable
    fun OfflineItem(modifier: Modifier = Modifier) {
        ItemStateIconImpl(
            resource = Res.drawable.item_offline,
            contentDescription = "Module is offline",
            color = Color(209, 66, 44),
            modifier = modifier
        )
    }


    /**
     * The icon used to indicate an online item.
     */
    @Composable
    fun OnlineItem(modifier: Modifier = Modifier) {
        ItemStateIconImpl(
            resource = Res.drawable.item_online,
            contentDescription = "Module is online",
            color = Color(180, 170, 80),
            modifier = modifier
        )
    }


    /**
     * The icon used to indicate an active item.
     */
    @Composable
    fun ActiveItem(modifier: Modifier = Modifier) {
        ItemStateIconImpl(
            resource = Res.drawable.item_active,
            contentDescription = "Module is active",
            color = Color(0, 170, 0),
            modifier = modifier
        )
    }


    /**
     * The icon used to indicate an overloaded item.
     */
    @Composable
    fun OverloadedItem(modifier: Modifier = Modifier) {
        ItemStateIconImpl(
            resource = Res.drawable.item_overloaded,
            contentDescription = "Module is overloaded",
            color = Color(219, 115, 76),
            modifier = modifier
        )
    }


    /**
     * The icon indicating some information is available.
     */
    @Composable
    fun Info(
        contentDescription: String? = null,
        modifier: Modifier = Modifier
    ) {
        Icon(
            imageVector = TheorycrafterTheme.iconStyle.Info,
            contentDescription = contentDescription,
            modifier = modifier
        )
    }


    /**
     * The icon for showing (Eve) item info.
     */
    @Composable
    fun EveItemInfo(
        contentDescription: String? = null,
        modifier: Modifier = Modifier
    ) {
        Icon(
            imageVector = TheorycrafterTheme.iconStyle.Info,
            contentDescription = contentDescription,
            modifier = modifier
        )
    }


    /**
     * The icon for search fields.
     */
    @Composable
    fun Search(
        contentDescription: String? = null,
        modifier: Modifier = Modifier
    ) {
        Icon(
            imageVector = TheorycrafterTheme.iconStyle.Search,
            contentDescription = contentDescription,
            modifier = modifier
        )
    }


    /**
     * The [ImageVector] for the menu button icon.
     */
    val MenuImageVector: ImageVector = TheorycrafterTheme.iconStyle.Menu


    /**
     * The icon for the settings button.
     */
    @Composable
    fun Settings(
        contentDescription: String? = null,
        modifier: Modifier = Modifier
    ) {
        Icon(
            imageVector = TheorycrafterTheme.iconStyle.Settings,
            contentDescription = contentDescription,
            modifier = modifier
        )
    }


    /**
     * The icon for the market tree button.
     */
    @Composable
    fun Market(
        contentDescription: String? = null,
        modifier: Modifier = Modifier
    ) {
        Icon(
            imageVector = TheorycrafterTheme.iconStyle.Storefront,
            contentDescription = contentDescription,
            modifier = modifier
        )
    }


    /**
     * The icon for the "Graphs" button.
     */
    @Composable
    fun Graphs(
        contentDescription: String? = null,
        modifier: Modifier = Modifier
    ) {
        Icon(
            imageVector = TheorycrafterTheme.iconStyle.QueryStats,
            contentDescription = contentDescription,
            modifier = modifier
        )
    }


    /**
     * The icon for the "Doctrines" button.
     */
    @Composable
    fun Doctrines(
        contentDescription: String? = null,
        modifier: Modifier = Modifier
    ) {
        Icon(
            imageVector = TheorycrafterTheme.iconStyle.Rocket,
            contentDescription = contentDescription,
            modifier = modifier
        )
    }


    /**
     * The icon used to mark the default skill set.
     */
    @Composable
    fun DefaultSkillSet(modifier: Modifier = Modifier) {
        Icon(
            imageVector = TheorycrafterTheme.iconStyle.Star,
            contentDescription = null,
            modifier = modifier.height(TheorycrafterTheme.sizes.defaultSkillSetIcon)
        )
    }


    /**
     * The icon for moving something up a row.
     */
    @Composable
    fun MoveUp() {
        Icon(TheorycrafterTheme.iconStyle.MoveUp)
    }


    /**
     * The icon for moving something down a row.
     */
    @Composable
    fun MoveDown() {
        Icon(TheorycrafterTheme.iconStyle.MoveDown)
    }


    /**
     * The icon for adding something.
     */
    @Composable
    fun Add() {
        Icon(TheorycrafterTheme.iconStyle.Add)
    }


    /**
     * The icon for removing something.
     */
    @Composable
    fun Remove() {
        Icon(TheorycrafterTheme.iconStyle.Remove)
    }


    /**
     * The icon for applying all cross-fit friendly effects.
     */
    @Composable
    fun ApplyCrossFitFriendlyEffects() {
        Icon(TheorycrafterTheme.iconStyle.SyncAlt)
    }


    /**
     * The icon for a cancel action.
     */
    @Composable
    fun Cancel(modifier: Modifier = Modifier) {
        Icon(
            imageVector = TheorycrafterTheme.iconStyle.Cancel,
            modifier = modifier
        )
    }


    /**
     * The icon for a small x.
     */
    @Composable
    fun Close(modifier: Modifier = Modifier) {
        Icon(
            imageVector = TheorycrafterTheme.iconStyle.Close,
            modifier = modifier
        )
    }


    /**
     * The icon for a grouped/ungrouped state.
     */
    @Composable
    fun Grouped(
        grouped: Boolean,
        modifier: Modifier
    ) {
        Icon(
            imageVector = with(TheorycrafterTheme.iconStyle) {
                if (grouped) Link else LinkOff
            },
            modifier = modifier
        )
    }


    /**
     * A standard expand/collapse icon.
     */
    @Composable
    fun TreeListExpandCollapse(
        expanded: Boolean,
        modifier: Modifier,
    ) {
        Icon(
            modifier = modifier,
            imageVector = if (expanded)
                TheorycrafterTheme.iconStyle.KeyboardArrowDown
            else
                TheorycrafterTheme.autoMirroredIconStyle.KeyboardArrowRight,
            contentDescription = if (expanded) "Expanded" else "Collapsed",
        )
    }


    /**
     * The icon for tournaments.
     */
    @Composable
    fun Tournaments(modifier: Modifier = Modifier) {
        Icon(
            imageVector = TheorycrafterTheme.iconStyle.EmojiEvents,
            modifier = modifier
        )
    }


    /**
     * The icon for the prices settings pane.
     */
    @Composable
    fun Prices(modifier: Modifier = Modifier) {
        Icon(
            imageVector = TheorycrafterTheme.iconStyle.Money,
            contentDescription = "Prices",
            modifier = modifier
        )
    }


    /**
    * The icon for loading charges into modules.
     */
    @Composable
    fun LoadCharges() {
        Icon(TheorycrafterTheme.autoMirroredIconStyle.Input)
    }


    /**
     * The icon for a warning.
     */
    @Composable
    fun Warning(modifier: Modifier = Modifier) {
        Icon(
            imageVector = TheorycrafterTheme.iconStyle.Warning,
            contentDescription = null,
            tint = TheorycrafterTheme.colors.base().warningContent,
            modifier = modifier
        )
    }


    /**
     * The icon for a green "OK" checkmark.
     */
    @Composable
    fun OkCheckmark(modifier: Modifier = Modifier) {
        Icon(
            imageVector = TheorycrafterTheme.iconStyle.Check,
            contentDescription = null,
            tint = TheorycrafterTheme.colors.base().successContent,
            modifier = modifier
        )
    }


    /**
     * The icon for the appearance settings.
     */
    @Composable
    fun AppearanceSettings(modifier: Modifier = Modifier) {
        Icon(
            imageVector = TheorycrafterTheme.iconStyle.Contrast,
            contentDescription = "Appearance",
            modifier = modifier
        )
    }


    /**
     * The icon for the skill set settings.
     */
    @Composable
    fun SkillSetSettings(modifier: Modifier = Modifier) {
        Icon(
            imageVector = TheorycrafterTheme.iconStyle.Looks5,
            contentDescription = "Skill Sets",
            modifier = modifier
        )
    }


    /**
     * The icon for the tracking consent settings pane.
     */
    @Composable
    fun TrackingConsent(modifier: Modifier = Modifier) {
        Icon(
            imageVector = when (TheorycrafterContext.settings.analytics.consent) {
                AnalyticsConsent.Yes -> TheorycrafterTheme.iconStyle.SentimentSatisfied
                AnalyticsConsent.No -> TheorycrafterTheme.iconStyle.SentimentDissatisfied
                AnalyticsConsent.Undecided -> TheorycrafterTheme.iconStyle.SentimentNeutral
            },
            contentDescription = "Tracking Consent",
            modifier = modifier
        )
    }


    /**
     * The icon for the Theorycrafter updates settings pane.
     */
    @Composable
    fun SoftwareUpdates(modifier: Modifier = Modifier) {
        Icon(
            imageVector = TheorycrafterTheme.iconStyle.BrowserUpdated,
            contentDescription = "Updates",
            modifier = modifier
        )
    }


    /**
    * The icon for the "About" settings pane.
     */
    @Composable
    fun AboutSettings(modifier: Modifier = Modifier) {
        Icon(
            imageVector = TheorycrafterTheme.iconStyle.Copyright,
            contentDescription = "About",
            modifier = modifier
        )
    }


    /**
     * The icon for a push-pin.
     */
    @Composable
    fun PushPin(modifier: Modifier = Modifier) {
        Icon(
            imageVector = TheorycrafterTheme.iconStyle.PushPin,
            contentDescription = null,
            modifier = modifier
        )
    }


    /**
     * The icon for adding a tag.
     */
    @Composable
    fun AddTag(modifier: Modifier = Modifier) {
        Icon(
            imageVector = TheorycrafterTheme.iconStyle.NewLabel,
            contentDescription = "Add tag",
            modifier = modifier
        )
    }


    /**
     * The icon for a fit optimization action.
     */
    @Composable
    fun OptimizeFit() {
        Icon(vectorResource(Res.drawable.optimize))
    }


    /**
     * The icon indicating a ship is a flagship.
     */
    @Composable
    fun Flagship(
        modifier: Modifier = Modifier
    ) {
        Icon(
            imageVector = TheorycrafterTheme.iconStyle.Flag,
            modifier = modifier
        )
    }


}


/**
 * A variant of [Icon] that doesn't require a content description.
 */
@Composable
private fun Icon(
    imageVector: ImageVector,
    modifier: Modifier = Modifier,
) {
    Icon(
        imageVector = imageVector,
        contentDescription = null,
        modifier = modifier
    )
}


/**
 * An icon representing a module or drone state.
 */
@Composable
private fun ItemStateIconImpl(
    resource: DrawableResource,
    contentDescription: String?,
    color: Color,
    modifier: Modifier
) {
    Image(
        imageVector = vectorResource(resource),
        contentDescription = contentDescription,
        colorFilter = ColorFilter.tint(color),
        contentScale = ContentScale.Fit,  // Scale with the size of the module name text
        modifier = modifier
            .size(TheorycrafterTheme.sizes.itemStateIconSize)
    )
}


/**
 * Cache of Eve object loaded bitmap images.
 */
private val eveObjectPainterCache = mutableMapOf<EveObjectWithIcon, Painter?>()


/**
 * Returns a cached painter of the given bitmap resource from the EveData module.
 */
@OptIn(ExperimentalResourceApi::class)
@Composable
fun cachedEveResourcePainter(eveObject: EveObjectWithIcon): Painter? {
    return eveObjectPainterCache.getOrPut(eveObject) {
        runCatching {
            val bytes = eveObject.loadIconBytes() ?: return@runCatching null
            BitmapPainter(bytes.decodeToImageBitmap())
        }.getOrNull()
    }
}


/**
 * The [ImageVector] used when a resource image is missing.
 */
private val MissingResourceImageVector = TheorycrafterTheme.autoMirroredIconStyle.HelpCenter


/**
 * An [Image] that draws the image loaded from the given EveData resource.
 */
@Composable
private fun EveResourceImage(
    eveObject: EveObjectWithIcon,
    contentDescription: String?,
    modifier: Modifier = Modifier,
    alignment: Alignment = Alignment.Center,
    contentScale: ContentScale = ContentScale.Fit,
    alpha: Float = DefaultAlpha,
    colorFilter: ColorFilter? = null
) {
    val painter = cachedEveResourcePainter(eveObject)
    if (painter != null) {
        Image(
            painter = painter,
            contentDescription = contentDescription,
            modifier = modifier,
            alignment = alignment,
            contentScale = contentScale,
            alpha = alpha,
            colorFilter = colorFilter,
        )
    } else {
        Image(
            imageVector = MissingResourceImageVector,
            contentDescription = contentDescription,
            modifier = modifier,
            alignment = alignment,
            contentScale = contentScale,
            alpha = alpha,
            colorFilter = ColorFilter.tint(LocalContentColor.current.copy(alpha = LocalContentAlpha.current))
        )
    }
}
