//     NEC Laboratories Europe GmbH
//
//     PROPRIETARY INFORMATION
//
// The software and its source code contain valuable trade secrets and
// shall be maintained in confidence and treated as confidential
// information. The software may only be used for evaluation and/or
// testing purposes, unless otherwise explicitly stated in a written
// agreement with NEC Laboratories Europe GmbH.
//
// Any unauthorized publication, transfer to third parties or
// duplication of the object or source code - either totally or in
// part - is strictly prohibited.
//
//          Copyright (c) 2021 NEC Laboratories Europe GmbH
//          All Rights Reserved.
//
// Authors: Konstantin Munichev <konstantin.munichev@neclab.eu>
//
//
// NEC Laboratories Europe GmbH DISCLAIMS ALL WARRANTIES, EITHER
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO IMPLIED WARRANTIES
// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE AND THE
// WARRANTY AGAINST LATENT DEFECTS, WITH RESPECT TO THE PROGRAM AND
// THE ACCOMPANYING DOCUMENTATION.
//
// NO LIABILITIES FOR CONSEQUENTIAL DAMAGES: IN NO EVENT SHALL NEC
// Laboratories Europe GmbH or ANY OF ITS SUBSIDIARIES BE LIABLE FOR
// ANY DAMAGES WHATSOEVER (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR
// LOSS OF BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF
// INFORMATION, OR OTHER PECUNIARY LOSS AND INDIRECT, CONSEQUENTIAL,
// INCIDENTAL, ECONOMIC OR PUNITIVE DAMAGES) ARISING OUT OF THE USE OF
// OR INABILITY TO USE THIS PROGRAM, EVEN IF NEC Laboratories Europe
// GmbH HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
//
// THIS HEADER MAY NOT BE EXTRACTED OR MODIFIED IN ANY WAY.

import io.ktor.client.*
import io.ktor.client.engine.cio.*
import io.ktor.client.features.*
import io.ktor.client.request.*
import io.ktor.utils.io.jvm.javaio.*
import kotlinx.serialization.ExperimentalSerializationApi
import proto.Config
import proto.Config.DltConfig

@OptIn(ExperimentalSerializationApi::class)
suspend fun main(args: Array<String>) {
    // TODO: default configuration file
    val cfg = DltConfig.newBuilder().setWallet("wallet").setConnectionFile("config/connection-org1.json")
        .setUser("appUser")
        .setChannel("dlt")
        .setContract("basic").setCaCertFile("config/ca.org1.example.com-cert.pem").setCaUrl("https://s2:7054")
        .setCaAdmin("admin").setCaAdminSecret("adminpw").setMsp("Org1MSP").setAffiliation("org1.department1")
        .build()
    val cfgBytes = cfg.toByteArray()

    val client = HttpClient(CIO) {
        HttpResponseValidator {
            validateResponse { response ->
                println(response.status)
            }
        }
    }

    try {
        client.post<ByteArray>("http://localhost:8080/dlt/configure") {
            body = cfgBytes
        }
    } catch (e: ClientRequestException) {
        println(e.response.status)
        println(String(e.response.content.toInputStream().readAllBytes()))
    }

    try {
        val config = client.get<ByteArray>("http://localhost:8080/dlt/configure")
        println(DltConfig.parseFrom(config))
    } catch (e: ClientRequestException) {
        println(e.response.status)
        println(String(e.response.content.toInputStream().readAllBytes()))
    }

    val uuid = "41f4d2e2-f4ef-4c81-872a-c32f2d26b2ca"
    try {
        val record = client.get<ByteArray>("http://localhost:8080/dlt/record") {
            body = uuid
        }
        println(Config.DltRecord.parseFrom(record))
    } catch (e: ClientRequestException) {
        println(e.response.status)
        println(String(e.response.content.toInputStream().readAllBytes()))
    }

    val id = Config.DltRecordId.newBuilder().setUuid(uuid).build()
    val record = Config.DltRecord.newBuilder().setId(id).setOperation(Config.DltRecordOperation.ADD)
        .setType(Config.DltRecordType.DEVICE).setJson("{}").build()
    try {
        val result = client.post<ByteArray>("http://localhost:8080/dlt/record") {
            body = record.toByteArray()
        }
        println(String(result))
        val requestedRecord = client.get<ByteArray>("http://localhost:8080/dlt/record") {
            body = uuid
        }
        println(Config.DltRecord.parseFrom(requestedRecord))
    } catch (e: ClientRequestException) {
        println(e.response.status)
        println(String(e.response.content.toInputStream().readAllBytes()))
    }

    try {
        val newRecord = Config.DltRecord.newBuilder().setId(id).setOperation(Config.DltRecordOperation.UPDATE)
            .setType(Config.DltRecordType.UNKNOWN).setJson("{}").build()
        val result = client.post<ByteArray>("http://localhost:8080/dlt/record") {
            body = newRecord.toByteArray()
        }
        println(String(result))
        val requestedRecord = client.get<ByteArray>("http://localhost:8080/dlt/record") {
            body = uuid
        }
        println(Config.DltRecord.parseFrom(requestedRecord))
    } catch (e: ClientRequestException) {
        println(e.response.status)
        println(String(e.response.content.toInputStream().readAllBytes()))
    }

    try {
        val newRecord = Config.DltRecord.newBuilder().setId(id).setOperation(Config.DltRecordOperation.DISABLE)
            .setType(Config.DltRecordType.SLICE).setJson("{}").build()
        val result = client.post<ByteArray>("http://localhost:8080/dlt/record") {
            body = newRecord.toByteArray()
        }
        println(String(result))
        val requestedRecord = client.get<ByteArray>("http://localhost:8080/dlt/record") {
            body = uuid
        }
        println(Config.DltRecord.parseFrom(requestedRecord))
    } catch (e: ClientRequestException) {
        println(e.response.status)
        println(String(e.response.content.toInputStream().readAllBytes()))
    }
}