/*
 * Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
 * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
 */

package kotlin.js

internal typealias BitMask = IntArray

private fun bitMaskWith(activeBit: Int): BitMask {
    val numberIndex = activeBit shr 5
    val intArray = IntArray(numberIndex + 1)
    val positionInNumber = activeBit and 31
    val numberWithSettledBit = 1 shl positionInNumber
    intArray[numberIndex] = intArray[numberIndex] or numberWithSettledBit
    return intArray
}

internal fun BitMask.isBitSet(possibleActiveBit: Int): Boolean {
    val numberIndex = possibleActiveBit shr 5
    if (numberIndex > size) return false
    val positionInNumber = possibleActiveBit and 31
    val numberWithSettledBit = 1 shl positionInNumber
    return get(numberIndex) and numberWithSettledBit != 0
}

private fun compositeBitMask(capacity: Int, masks: Array<BitMask>): BitMask {
    return IntArray(capacity) { i ->
        var result = 0
        for (mask in masks) {
            if (i < mask.size) {
                result = result or mask[i]
            }
        }
        result
    }
}

internal fun implement(interfaces: Array<dynamic>): BitMask {
    var maxSize = 1
    val masks = js("[]")

    for (i in interfaces) {
        var currentSize = maxSize
        val imask: BitMask? = i.prototype.`$imask$` ?: i.`$imask$`

        if (imask != null) {
            masks.push(imask)
            currentSize = imask.size
        }

        val iid: Int? = i.`$metadata$`.iid
        val iidImask: BitMask? = iid?.let { bitMaskWith(it) }

        if (iidImask != null) {
            masks.push(iidImask)
            currentSize = JsMath.max(currentSize, iidImask.size)
        }

        if (currentSize > maxSize) {
            maxSize = currentSize
        }
    }

    return compositeBitMask(maxSize, masks)
}
