/*
 * Copyright (C) 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package android.uirendering.cts.testinfrastructure

import android.app.Activity
import android.content.pm.ActivityInfo
import android.content.res.Configuration
import android.graphics.Point
import android.os.Bundle
import android.os.Handler
import android.os.Message
import android.uirendering.cts.R
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.annotation.Nullable
import org.junit.Assert.assertNotNull
import org.junit.Assert.assertTrue
import java.util.concurrent.CountDownLatch
import java.util.concurrent.TimeUnit

class Offset(val dx: Float, val dy: Float) {
    override fun equals(other: Any?): Boolean {
        return this === other || (other as? Offset)?.let {
            dx == other.dx && dy == other.dy
        } ?: false
    }

    override fun hashCode(): Int = dx.hashCode() xor dy.hashCode()
}

/**
 * A generic activity that uses a view specified by the user.
 */
class DrawActivity : Activity() {
    companion object {
        internal const val EXTRA_WIDE_COLOR_GAMUT = "DrawActivity.WIDE_COLOR_GAMUT"
        internal const val EXTRA_USE_FORCE_DARK = "DrawActivity.USE_FORCE_DARK"

        private const val TIME_OUT_MS: Long = 10000

        private const val LAYOUT_MSG = 1
        private const val CANVAS_MSG = 2
    }

    private val mLock = java.lang.Object()
    private var mPositionInfo: ActivityTestBase.TestPositionInfo? = null

    private lateinit var mHandler: Handler
    private lateinit var mTestContainer: ViewGroup

    private var mView: View? = null

    private var mViewInitializer: ViewInitializer? = null

    public override fun onCreate(bundle: Bundle?) {
        super.onCreate(bundle)

        if (intent.getBooleanExtra(EXTRA_USE_FORCE_DARK, false)) {
            forceUiMode(Configuration.UI_MODE_NIGHT_YES)
            setTheme(R.style.AutoDarkTheme)
        } else {
            forceUiMode(Configuration.UI_MODE_NIGHT_NO)
        }

        if (intent.getBooleanExtra(EXTRA_WIDE_COLOR_GAMUT, false)) {
            window.colorMode = ActivityInfo.COLOR_MODE_WIDE_COLOR_GAMUT
        }

        window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or
                View.SYSTEM_UI_FLAG_FULLSCREEN
        mHandler = RenderSpecHandler()

        setContentView(R.layout.test_container)
        mTestContainer = findViewById(R.id.test_content_wrapper)
    }

    private fun forceUiMode(mode: Int) {
        if (resources.configuration.uiMode != mode) {
            val newConfig = Configuration(resources.configuration)
            newConfig.uiMode = mode
            resources.updateConfiguration(newConfig, resources.displayMetrics)
            onConfigurationChanged(newConfig)
        }
    }

    fun enqueueRenderSpecAndWait(
        layoutId: Int,
        canvasClient: CanvasClient?, @Nullable viewInitializer: ViewInitializer?,
        useHardware: Boolean, usePicture: Boolean
    ): ActivityTestBase.TestPositionInfo {
        (mHandler as RenderSpecHandler).setViewInitializer(viewInitializer)
        val arg2 = if (useHardware) View.LAYER_TYPE_NONE else View.LAYER_TYPE_SOFTWARE
        synchronized(mLock) {
            if (canvasClient != null) {
                mHandler.obtainMessage(CANVAS_MSG, if (usePicture) 1 else 0,
                    arg2, canvasClient
                ).sendToTarget()
            } else {
                mHandler.obtainMessage(LAYOUT_MSG, layoutId, arg2)
                    .sendToTarget()
            }

            try {
                mLock.wait(TIME_OUT_MS)
            } catch (e: InterruptedException) {
                throw AssertionError(e)
            }

        }
        assertNotNull("Timeout waiting for draw", mPositionInfo)
        return mPositionInfo!!
    }

    fun waitForRedraw() {
        synchronized(mLock) {
            mHandler.post {
                mTestContainer.invalidate()
                notifyOnDrawCompleted()
            }
            try {
                mLock.wait(TIME_OUT_MS)
            } catch (e: InterruptedException) {
                throw AssertionError(e)
            }
        }
    }

    private fun notifyOnDrawCompleted() {
        mTestContainer.viewTreeObserver.registerFrameCommitCallback {
            val location = IntArray(2)
            mTestContainer.getLocationInWindow(location)
            val surfaceOffset = Point(location[0], location[1])
            mTestContainer.getLocationOnScreen(location)
            val screenOffset = Point(location[0], location[1])
            synchronized(mLock) {
                mPositionInfo = ActivityTestBase.TestPositionInfo(
                    surfaceOffset, screenOffset
                )
                mLock.notify()
            }
        }
    }

    fun reset() {
        val fence = CountDownLatch(1)
        mHandler.post {
            mViewInitializer?.teardownView()
            mViewInitializer = null
            mView = null
            mTestContainer.removeAllViews()
            fence.countDown()
        }
        assertTrue(fence.await(TIME_OUT_MS, TimeUnit.MILLISECONDS))
    }

    private inner class RenderSpecHandler : Handler() {

        fun setViewInitializer(viewInitializer: ViewInitializer?) {
            mViewInitializer = viewInitializer
        }

        override fun handleMessage(message: Message) {
            mTestContainer.removeAllViews()
            when (message.what) {
                LAYOUT_MSG -> {
                    mView = LayoutInflater.from(this@DrawActivity).inflate(
                        message.arg1, mTestContainer, false
                    )
                }

                CANVAS_MSG -> {
                    val canvasClientView = CanvasClientView(this@DrawActivity)
                    canvasClientView.setCanvasClient(message.obj as CanvasClient)
                    if (message.arg1 != 0) {
                        canvasClientView.setUsePicture(true)
                    }
                    mView = canvasClientView
                }
            }

            if (mView == null) {
                throw IllegalStateException("failed to inflate test content")
            }

            mTestContainer.addView(
                mView, ViewGroup.LayoutParams.MATCH_PARENT,
                ViewGroup.LayoutParams.MATCH_PARENT
            )

            if (mViewInitializer != null) {
                mViewInitializer!!.initializeView(mView)
            }

            // set layer on wrapper parent of view, so view initializer
            // can control layer type of View under test.
            mTestContainer.setLayerType(message.arg2, null)

            notifyOnDrawCompleted()
        }
    }

    override fun onPause() {
        super.onPause()
        if (mViewInitializer != null) {
            throw IllegalStateException("Failed to reset() after running test")
        }
    }

    override fun finish() {
        // Ignore
    }

    /** Call this when all the tests that use this activity have completed.
     * This will then clean up any internal state and finish the activity.  */
    fun allTestsFinished() {
        super.finish()
    }
}
