/*
 * Use of this source code is governed by the MIT license that can be
 * found in the LICENSE file.
 */

package org.rust.lang.core.psi.ext

import com.intellij.lang.ASTNode
import com.intellij.psi.PsiElement
import com.intellij.psi.search.SearchScope
import com.intellij.psi.stubs.IStubElementType
import org.rust.ide.icons.RsIcons
import org.rust.lang.core.macros.RsExpandedElement
import org.rust.lang.core.psi.RsElementTypes.UNION
import org.rust.lang.core.psi.RsPsiImplUtil
import org.rust.lang.core.psi.RsStructItem
import org.rust.lang.core.stubs.RsStructItemStub
import org.rust.lang.core.types.RsPsiTypeImplUtil
import org.rust.lang.core.types.ty.Ty
import javax.swing.Icon

val RsStructItem.union: PsiElement?
    get() = node.findChildByType(UNION)?.psi


enum class RsStructKind {
    STRUCT,
    UNION
}

val RsStructItem.kind: RsStructKind get() {
    val hasUnion = greenStub?.isUnion ?: (union != null)
    return if (hasUnion) RsStructKind.UNION else RsStructKind.STRUCT
}

val RsStructItem.isTupleStruct get() = tupleFields != null

abstract class RsStructItemImplMixin : RsStubbedNamedElementImpl<RsStructItemStub>, RsStructItem {

    constructor(node: ASTNode) : super(node)

    constructor(stub: RsStructItemStub, nodeType: IStubElementType<*, *>) : super(stub, nodeType)

    override fun getIcon(flags: Int): Icon {
        val baseIcon = when (kind) {
            RsStructKind.STRUCT -> RsIcons.STRUCT
            RsStructKind.UNION -> RsIcons.UNION
        }
        return iconWithVisibility(flags, baseIcon)
    }

    override val crateRelativePath: String? get() = RsPsiImplUtil.crateRelativePath(this)

    override val declaredType: Ty get() = RsPsiTypeImplUtil.declaredType(this)

    override fun getContext(): PsiElement? = RsExpandedElement.getContextImpl(this)

    override fun getUseScope(): SearchScope = RsPsiImplUtil.getDeclarationUseScope(this) ?: super.getUseScope()
}
