package es.verdnatura.presentation.testing

import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.graphics.Bitmap
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.pdf.PdfRenderer
import android.net.Uri
import android.os.Bundle
import android.os.Parcel
import android.os.ParcelFileDescriptor
import android.os.ResultReceiver
import android.util.Log
import android.view.View
import android.view.inputmethod.EditorInfo
import android.widget.Toast
import androidx.lifecycle.Observer
import es.verdnatura.R
import es.verdnatura.databinding.FragmentTestingPrintBinding
import es.verdnatura.presentation.base.BaseFragment
import es.verdnatura.presentation.view.component.CustomDialog
import es.verdnatura.presentation.view.feature.qr.QrFragmentViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import java.io.File
import java.io.IOException
import java.io.UnsupportedEncodingException


@Suppress("UNUSED_ANONYMOUS_PARAMETER")
class testPrint(
    var entryPoint: String = ""
) : BaseFragment<FragmentTestingPrintBinding, QrFragmentViewModel>(QrFragmentViewModel::class) {

    private var goBack: Boolean = false
    override fun getLayoutId(): Int = R.layout.fragment_testing_print
    private lateinit var customDialog: CustomDialog
    private var itemscaned = ""

    companion object {
        fun newInstance(entryPoint: String) = testPrint(entryPoint)
    }


    override fun init() {

        binding.splashProgress.visibility = View.GONE
        customDialog = CustomDialog(requireContext())

        setToolbar()
        setEvents()
        super.init()
    }

    private fun setToolbar() {

        binding.mainToolbar.toolbarTitle.text = entryPoint
    }

    override fun onPause() {
        goBack = true
        super.onPause()
    }


    private fun setEvents() {

        binding.mainToolbar.backButton.setOnClickListener {
            requireActivity().onBackPressed()
        }

        binding.buttonPrintTemplate.setOnClickListener {

            printTemplate()
        }

        binding.buttonPrintAll.setOnClickListener {

            printAllData()
        }
        binding.buttonPrintZpl.setOnClickListener {

            printZPL()
        }
        binding.buttonPrintStatus.setOnClickListener {
            printStatus()
        }

        binding.buttonPrintDisconnect.setOnClickListener {
            printDisconnect()
        }

        binding.buttonImgToPdf.setOnClickListener {
            convertImg()
        }

        binding.scanInput.requestFocus()
        binding.scanInput.setOnEditorActionListener { v, actionId, event ->

            if (actionId == EditorInfo.IME_ACTION_SEARCH || actionId == EditorInfo.IME_ACTION_DONE || actionId == 0) {


                goBack = false
                if (!binding.scanInput.text.isNullOrEmpty()) {
                    binding.splashProgress.visibility = View.VISIBLE
                    viewModel.qr_getCall(
                        getData(USER),
                        getData(PASSWORD),
                        binding.scanInput.text.toString()
                    )
                    itemscaned = binding.scanInput.text.toString()
                }

            }
            binding.scanInput.setText("")
            ma.hideKeyboard(binding.scanInput)
            return@setOnEditorActionListener true
        }
        // false

    }
    @Throws(IOException::class)
    fun getFileFromAssets(context: Context, fileName: String): File = File(context.cacheDir, fileName)
        .also {
            if (!it.exists()) {
                it.outputStream().use { cache ->
                    context.assets.open(fileName).use { inputStream ->
                        inputStream.copyTo(cache)
                    }
                }
            }
        }

    private fun convertImg() {

        val path: Uri = Uri.parse("file://android_asset/raw/test.pdf")

        //val newPath: String = path.toString()
        val filePath =  getFileFromAssets(requireContext(), "test.pdf").absolutePath
        val input = ParcelFileDescriptor.open(File(filePath), ParcelFileDescriptor.MODE_READ_ONLY)
        val renderer = PdfRenderer(input)


        val page = renderer.openPage(0)
        val bitmap = Bitmap.createBitmap(
            200, (200.toFloat() / page.width * page.height).toInt(), Bitmap.Config.ARGB_8888
        )
        page.render(bitmap, null, null, PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY)



        page.close()
        renderer.close()


// do something with the bitmap, like putting it on an ImageView
        binding.imageView.setImageBitmap(bitmap)
        page.close()
        renderer.close()
    }

    suspend fun renderSinglePage(filePath: String, width: Int) = withContext(Dispatchers.IO) {
        PdfRenderer(
            ParcelFileDescriptor.open(
                File(filePath),
                ParcelFileDescriptor.MODE_READ_ONLY
            )
        ).use { renderer ->
            renderer.openPage(0).renderAndClose(width)
        }
    }

    fun PdfRenderer.Page.renderAndClose(width: Int) = use {
        val bitmap = createBitmap(width)
        render(bitmap, null, null, PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY)
        bitmap
    }

    private fun PdfRenderer.Page.createBitmap(bitmapWidth: Int): Bitmap {
        val bitmap = Bitmap.createBitmap(
            bitmapWidth, (bitmapWidth.toFloat() / width * height).toInt(), Bitmap.Config.ARGB_8888
        )

        val canvas = Canvas(bitmap)
        canvas.drawColor(Color.WHITE)
        canvas.drawBitmap(bitmap, 0f, 0f, null)

        return bitmap
    }


    private fun printZPL() {
        var variableData = HashMap<String, String>()
        variableData.put("%PRODUCT_NAME%", "Apples")
        variableData.put("%MSRP%", "$1.00")
        variableData.put("%PCT%", "50")
        variableData.put("%FINAL%", "$0.50")
        variableData.put("%UPC_CODE%", "12345678")
        val passthroughData = """
            CT~~CD,~CC^~CT~
            ^XA~TA000~JSN^LT0^MNW^MTD^PON^PMN^LH0,0^JMA^PR4,4~SD10^JUS^LRN^CI0^XZ
            ^XA
            ^MMT
            ^PW591
            ^LL0203
            ^LS0
            ^FT171,82^A0N,27,26^FH\^FDBananas^FS
            ^FT222,107^A0N,17,16^FH\^FD$0.99^FS
            ^FT424,163^A0N,23,24^FB82,1,0,R^FH\^FD10^FS
            ^FT314,167^A0N,28,28^FH\^FD$0.89^FS
            ^FT367,107^A0N,17,16^FH\^FD8424245^FS
            ^FT471,138^A0N,14,14^FH\^FDYou saved:^FS
            ^FO451,119^GB103,54,2^FS
            ^FT171,20^A0N,17,16^FH\^FDPrintConnect Template Print Example^FS
            ^FT171,167^A0N,28,28^FH\^FDFinal Price:^FS
            ^FT171,51^A0N,17,16^FH\^FDProduct:^FS
            ^FT171,107^A0N,17,16^FH\^FDMSRP:^FS
            ^FT508,163^A0N,23,24^FH\^FD%^FS
            ^FT328,107^A0N,17,16^FH\^FDUPC:^FS
            ^FO171,119^GB259,0,2^FS
            ^PQ1,0,1,Y^XZ
            
            """.trimIndent()

        var passthroughDataBytes: ByteArray? = null

        try {
// Convert template ZPL string to a UTF-8 encoded byte array, which will be sent as an extra with the intent
            //templateBytes = templateData.getBytes("UTF-8");
            passthroughDataBytes = passthroughData.toByteArray()
        } catch (e: UnsupportedEncodingException) {
            // Handle exception
        }
        val intent = Intent()
        intent.component = ComponentName(
            "com.zebra.printconnect",
            "com.zebra.printconnect.print.PassthroughService"
        )

        intent.putExtra(
            "com.zebra.printconnect.PrintService.PASSTHROUGH_DATA",
            passthroughDataBytes
        )
        intent.putExtra(
            "com.zebra.printconnect.PrintService.RESULT_RECEIVER",
            buildIPCSafeReceiver(object : ResultReceiver(null) {

                override fun onReceiveResult(resultCode: Int, resultData: Bundle?) {
                    super.onReceiveResult(resultCode, resultData)

                    if (resultCode == 0) {
                        // Result code 0 indicates success
                    } else {
                        // Handle unsuccessful print
// Error message (null on successful print)
                        val errorMessage =
                            resultData?.getString("com.zebra.printconnect.PrintService.ERROR_MESSAGE")
                        Toast.makeText(context, errorMessage, Toast.LENGTH_LONG).show()
                    }
                }

            })
        )

        requireContext().startService(intent)
    }

    private fun printAllData() {

        var variableData = HashMap<String, String>()
        variableData.put("%PRODUCT_NAME%", "Apples")
        variableData.put("%MSRP%", "$1.00")
        variableData.put("%PCT%", "50")
        variableData.put("%FINAL%", "$0.50")
        variableData.put("%UPC_CODE%", "12345678")

        val templateData = """
            CT~~CD,~CC^~CT~
            ^XA~TA000~JSN^LT0^MNW^MTD^PON^PMN^LH0,0^JMA^PR4,4~SD10^JUS^LRN^CI0^XZ
            ^XA
            ^MMT
            ^PW591
            ^LL0203
            ^LS0
            ^FT171,82^A0N,27,26^FH\^FD%PRODUCT_NAME%^FS
            ^FT222,107^A0N,17,16^FH\^FD%MSRP%^FS
            ^FT424,163^A0N,23,24^FB82,1,0,R^FH\^FD%PCT%^FS
            ^FT314,167^A0N,28,28^FH\^FD%FINAL%^FS
            ^FT367,107^A0N,17,16^FH\^FD%UPC_CODE%^FS
            ^FT471,138^A0N,14,14^FH\^FDYou saved:^FS
            ^FO451,119^GB103,54,2^FS
            ^FT171,20^A0N,17,16^FH\^FDPrintConnect Template Print Example^FS
            ^FT171,167^A0N,28,28^FH\^FDFinal Price:^FS
            ^FT171,51^A0N,17,16^FH\^FDProduct:^FS
            ^FT171,107^A0N,17,16^FH\^FDMSRP:^FS
            ^FT508,163^A0N,23,24^FH\^FD%^FS
            ^FT328,107^A0N,17,16^FH\^FDUPC:^FS
            ^FO171,119^GB259,0,2^FS
            ^PQ1,0,1,Y^XZ
            
            """.trimIndent()


        var templateBytes: ByteArray? = null

        try {
// Convert template ZPL string to a UTF-8 encoded byte array, which will be sent as an extra with the intent
            //templateBytes = templateData.getBytes("UTF-8");
            templateBytes = templateData.toByteArray()
        } catch (e: UnsupportedEncodingException) {
            // Handle exception
            Log.d("VERDNATURA::","Error"+e.message)
        }
        val intent = Intent()
        intent.component = ComponentName(
            "com.zebra.printconnect",
            "com.zebra.printconnect.print.TemplatePrintWithContentService"
        )

        intent.putExtra(
            "com.zebra.printconnect.PrintService.TEMPLATE_DATA",
            templateBytes
        )
        intent.putExtra("com.zebra.printconnect.PrintService.VARIABLE_DATA", variableData)
        intent.putExtra(
            "com.zebra.printconnect.PrintService.RESULT_RECEIVER",
            buildIPCSafeReceiver(object : ResultReceiver(null) {

                override fun onReceiveResult(resultCode: Int, resultData: Bundle?) {
                    super.onReceiveResult(resultCode, resultData)

                    if (resultCode == 0) {
                        // Result code 0 indicates success
                    } else {
                        // Handle unsuccessful print
// Error message (null on successful print)
                        val errorMessage =
                            resultData?.getString("com.zebra.printconnect.PrintService.ERROR_MESSAGE")
                        Toast.makeText(context, errorMessage, Toast.LENGTH_LONG).show()
                    }
                }

            })
        )

        requireContext().startService(intent)
    }

    private fun printTemplate() {
        // Define a hash map of variable data
        // Strings used for keys will be replaced by their corresponding values in your template file's ZPL
        var variableData = HashMap<String, String>()
        variableData.put("%PRODUCT_NAME%", "Bananas")
        variableData.put("%MSRP%", "$1.00")
        variableData.put("%PCT%", "50")
        variableData.put("%FINAL%", "$0.50")
        variableData.put("%UPC_CODE%", "12345678")
        val intent = Intent()
        intent.component = ComponentName(
            "com.zebra.printconnect",
            "com.zebra.printconnect.print.TemplatePrintService"
        )

        intent.putExtra(
            "com.zebra.printconnect.PrintService.TEMPLATE_FILE_NAME",
            "PriceTagTemplate.zpl"
        )
        intent.putExtra("com.zebra.printconnect.PrintService.VARIABLE_DATA", variableData)
        intent.putExtra(
            "com.zebra.printconnect.PrintService.RESULT_RECEIVER",
            buildIPCSafeReceiver(object : ResultReceiver(null) {

                override fun onReceiveResult(resultCode: Int, resultData: Bundle?) {
                    super.onReceiveResult(resultCode, resultData)

                    if (resultCode == 0) {
                        // Result code 0 indicates success
                    } else {
                        // Handle unsuccessful print
                        // Error message (null on successful print)
                        val errorMessage =
                            resultData?.getString("com.zebra.printconnect.PrintService.ERROR_MESSAGE")
                        Toast.makeText(context, errorMessage, Toast.LENGTH_LONG).show()
                    }
                }

            })
        )

        requireContext().startService(intent)
    }

    private fun printStatus() {
        val intent = Intent()
        intent.component = ComponentName(
            "com.zebra.printconnect",
            "com.zebra.printconnect.print.GetPrinterStatusService"
        )
    Log.d("VERDNATURA::","Entrando en prinStatus")
        intent.putExtra(
            "com.zebra.printconnect.PrintService.RESULT_RECEIVER",
            buildIPCSafeReceiver(object : ResultReceiver(null) {

                override fun onReceiveResult(resultCode: Int, resultData: Bundle?) {
                    super.onReceiveResult(resultCode, resultData)

                    if (resultCode == 0) {
                        Log.d("VERDNATURA::","Result 0")
                        // Result code 0 indicates success
                        val printerStatusMap =
                            resultData!!.getSerializable("PrinterStatusMap") as HashMap<String, String>?
                        Toast.makeText(context, printerStatusMap.toString(), Toast.LENGTH_LONG).show()
                    } else {
                        // Handle unsuccessful print
                        // Error message (null on successful print)
                        Log.d("VERDNATURA::","Result <>0")
                        val errorMessage =
                            resultData?.getString("com.zebra.printconnect.PrintService.ERROR_MESSAGE")
                        Toast.makeText(context, errorMessage, Toast.LENGTH_LONG).show()
                    }
                }

            })
        )

    requireContext().startService(intent)
}
    private fun printDisconnect() {
        val intent = Intent()
        intent.component = ComponentName(
            "com.zebra.printconnect",
            "com.zebra.printconnect.print.UnselectPrinterService"
        )

        intent.putExtra(
            "com.zebra.printconnect.PrintService.RESULT_RECEIVER",
            buildIPCSafeReceiver(object : ResultReceiver(null) {

                override fun onReceiveResult(resultCode: Int, resultData: Bundle?) {
                    super.onReceiveResult(resultCode, resultData)

                    if (resultCode == 0) {
                        // Result code 0 indicates success
                        val printerStatusMap =
                            resultData!!.getSerializable("PrinterStatusMap") as HashMap<String, String>?
                        Toast.makeText(context, printerStatusMap.toString(), Toast.LENGTH_LONG).show()
                    } else {
                        // Handle unsuccessful print
                        // Error message (null on successful print)
                        val errorMessage =
                            resultData?.getString("com.zebra.printconnect.PrintService.ERROR_MESSAGE")
                        Toast.makeText(context, errorMessage, Toast.LENGTH_LONG).show()
                    }
                }

            })
        )

        requireContext().startService(intent)
    }
    private fun buildIPCSafeReceiver(resultReceiver: ResultReceiver): ResultReceiver? {
        val parcel = Parcel.obtain()
        resultReceiver.writeToParcel(parcel, 0)
        parcel.setDataPosition(0)
        val receiverForSending = ResultReceiver.CREATOR.createFromParcel(parcel)
        parcel.recycle()
        return receiverForSending
    }

    override fun observeViewModel() {

        with(viewModel) {
            qrresponse.observe(viewLifecycleOwner, Observer {
                binding.splashProgress.visibility = View.GONE
                if (it.isError) {

                    ma.messageWithSound(it.errorMessage + " " + itemscaned, true, false)

                } else {

                    customDialog.setTitle(getString(R.string.info))
                        .setDescription(
                            getString(R.string.operation) + itemscaned + "." + getString(
                                R.string.answer
                            ) + it.response
                        )
                        .setOkButton(getString(R.string.accept)) {
                            customDialog.dismiss()
                            binding.mainToolbar.backButton.performClick()
                        }.show()

                }

            })
        }

    }


}

