/*
 * Copyright (C) 2011 The Android Open Source Project
 * Copyright (c) 2018 Jim Andreas
 *
 * 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 com.jimandreas.handlerstudy.uithread

import android.app.Activity
import android.content.Intent
import android.graphics.Color
import android.graphics.PorterDuff
import android.net.Uri
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.os.Message
import android.support.design.widget.FloatingActionButton
import android.support.design.widget.Snackbar
import android.widget.SeekBar
import com.jimandreas.handlerstudy.customview.SpeedometerGauge
import com.jimandreas.handlerstudy.opengl.MyGLRenderer
import com.jimandreas.handlerstudy.opengl.MyGLSurfaceView
import com.jimandreas.handlerstudy.opengl.R
import kotlinx.coroutines.experimental.android.HandlerContext
import kotlinx.coroutines.experimental.android.UI
import kotlinx.coroutines.experimental.launch
import kotlinx.coroutines.experimental.runBlocking

data class SliderColor(var red: Int = 0, var green: Int = 0, var blue: Int = 0)

class MainActivity : Activity(), SeekBar.OnSeekBarChangeListener, Handler.Callback {

    private lateinit var sliderRed: SeekBar
    private lateinit var sliderGreen: SeekBar
    private lateinit var sliderBlue: SeekBar
    private lateinit var surfaceView: MyGLSurfaceView
    private lateinit var speedometer: SpeedometerGauge
    private lateinit var fab: FloatingActionButton

    private lateinit var renderer: MyGLRenderer
    private val sliderColor = SliderColor(50, 75, 50)

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.main)

        sliderRed = findViewById(R.id.slider_red)
        sliderGreen = findViewById(R.id.slider_green)
        sliderBlue = findViewById(R.id.slider_blue)
        surfaceView = findViewById(R.id.surface_view)
        speedometer = findViewById(R.id.rpm_value)
        fab = findViewById(R.id.info_fab)

        val handler = Handler(Looper.getMainLooper(), this)
        /*
         * set up the OpenGL system
         */
        // Request an OpenGL ES 2.0 compatible context.
        surfaceView.setEGLContextClientVersion(2)
        renderer = MyGLRenderer(surfaceView, handler)
        surfaceView.setRenderer(renderer)

        // http://stackoverflow.com/a/19265149/3853712
        val sliderList = arrayListOf(sliderRed, sliderGreen, sliderBlue)
        val colorList = arrayListOf(-0x10000, -0x00ff0100, -0xffff01)
        sliderList.forEachIndexed { index, it ->
            it.progressDrawable.setColorFilter(colorList[index], PorterDuff.Mode.SRC_IN)
            it.thumb.setColorFilter(colorList[index], PorterDuff.Mode.SRC_IN)
            it.setOnSeekBarChangeListener(this)
        }

        /*
         * if this is a rotation (have old state), then don't init sliders - they are preserved
         */
//        if (savedInstanceState == null) {
//            sliderRed.progress = 50
//            sliderGreen.progress = 75 // greenish initially, better than grey!
//            sliderBlue.progress = 50
//        }

        // set up the speedometer custom view
        initSpeedometer()

        sliderRed.progress = sliderColor.red
        sliderGreen.progress = sliderColor.green
        sliderBlue.progress = sliderColor.blue

        /*
         * FAB button (floating action button = FAB) to get more information
         *    Vector to the website for more info
         */
        fab.setOnClickListener { view ->
            val snackbar = Snackbar.make(view, "website", Snackbar.LENGTH_LONG)

            snackbar.setAction("View website") {
                val intent = Intent(Intent.ACTION_VIEW)
                intent.data = Uri.parse(
                        "https://github.com/jimandreas/UIandOpenGLthreading")
                startActivity(intent)
            }
            snackbar.show()
        }
    }

    /**
     * SeekBar override methods - feed adjustments to the triangle color
     * by calling into the Renderer on the OpenGL thread
     *
     * @param seekBar  The SeekBar whose progress has changed
     * @param progress how far we are - using default 0..100
     * @param fromUser True if the progress change was initiated by the user.
     */
    override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
        when {
            seekBar === sliderRed -> sliderColor.red = progress
            seekBar === sliderGreen -> sliderColor.green = progress
            else -> sliderColor.blue = progress
        }
        surfaceView.queueEvent { renderer.updateColor2(sliderColor) }
    }

    override fun onStartTrackingTouch(seekBar: SeekBar) {
    }

    override fun onStopTrackingTouch(seekBar: SeekBar) {
    }


    override fun onPause() {
        super.onPause()
        // The following call pauses the rendering thread.
        // If your OpenGL application is memory intensive,
        // you should consider de-allocating objects that
        // consume significant memory here.
        //        mGLView.onPause();
    }

    override fun onResume() {
        super.onResume()
        // The following call resumes a paused rendering thread.
        // If you de-allocated graphic objects for onPause()
        // this is a good place to re-allocate them.
        //        mGLView.onResume();
    }

/*    private fun resetSlider(
            @MyGLRenderer.RenderSetColor which_color: Int,
            progress: Int) {

        surfaceView.queueEvent { renderer.updateColor(which_color, progress) }

    }*/

    private fun initSpeedometer() {
        // configure value range and ticks
        speedometer.maxSpeed = 300.0
        speedometer.majorTickStep = 30.0
        speedometer.minorTicks = 2

        // Configure value range colors
        speedometer.addColoredRange(30.0, 140.0, Color.GREEN)
        speedometer.addColoredRange(140.0, 180.0, Color.YELLOW)
        speedometer.addColoredRange(180.0, 400.0, Color.RED)
    }

    /**
     * receive messages from the renderer
     * Currently:
     * GL_READY - the GL components are created - instance state can
     * now be set (like for device rotation)
     * UPDATE_RPM - RPM indicator - to be implemented
     * @param msg  message sent from renderer
     * @return true
     */

    override fun handleMessage(msg: Message): Boolean {
        when (msg.what) {
            UI_MESSAGE_GL_READY -> {
                renderer.updateColor2(sliderColor)
            }
            UI_MESSAGE_UPDATE_RPM -> {
                var rpm = msg.arg1
                if (rpm < 0) {
                    rpm *= -1
                }
                speedometer.speed = rpm.toDouble()
            }
        }
        return true
    }

    fun signalingUIFunction() = runBlocking<Unit> {
        launch(UI) {
            // will get dispatched to ForkJoinPool.commonPool (or equivalent)
            println("      'CommonPool': I'm working in thread ${Thread.currentThread().name}")
        }
    }

    fun signalingOpenGLFunction() = runBlocking<Unit> {

        val UI = HandlerContext(Handler(Looper.getMainLooper()), "UI")
        launch(UI) {
            // will get dispatched to ForkJoinPool.commonPool (or equivalent)
            println("      'CommonPool': I'm working in thread ${Thread.currentThread().name}")
        }
    }

    companion object {

        /**
         * Handler messages
         * for more information on the IntDef in the Studio annotation library:
         *
         * https://noobcoderblog.wordpress.com/2015/04/12/java-enum-and-android-intdefstringdef-annotation/
         */
        const val UI_MESSAGE_GL_READY = 1
        const val UI_MESSAGE_UPDATE_RPM = 2
    }
}