// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you 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 bitcoinplugin

import (
	"crypto/sha256"
	"encoding/hex"
	"fmt"
	"math/big"

	"github.com/apache/incubator-milagro-dta/libs/cryptowallet"
	"github.com/apache/incubator-milagro-dta/libs/documents"
	"github.com/apache/incubator-milagro-dta/pkg/common"
	"github.com/btcsuite/btcd/btcec"
	"github.com/pkg/errors"
)

func deriveFinalPrivateKey(s *Service, order documents.OrderDoc, beneficiariesSikeSK []byte, beneficiariesSeed []byte, beneficiaryIDDocumentCID string, nodeID string, signingBlsPK []byte) (string, error) {
	if beneficiaryIDDocumentCID != "" {
		//we are using the beneficiary specified in order Part 3
		beneficiaryBlob := order.OrderPart3.BeneficiaryEncryptedData

		//Decrypt the Envelope intented for the Beneficiary
		privateKeyPart1of1, err := adhocEncryptedEnvelopeDecode(s, beneficiariesSikeSK, beneficiaryBlob, beneficiaryIDDocumentCID, signingBlsPK)
		if err != nil {
			return "", err
		}
		//Calculate the final private key by Eliptical Key addition of both parts
		privateKeyPart2of2 := order.OrderDocument.OrderPart4.Secret

		finalPrivateKey, err := addPrivateKeys(privateKeyPart1of1, privateKeyPart2of2)

		if err != nil {
			return "", err
		}
		return finalPrivateKey, err
	}

	//we are using the beneficiary specified in the order part 1
	privateKeyPart2of2 := order.OrderDocument.OrderPart4.Secret
	if order.OrderDocument.BeneficiaryCID != nodeID {
		//need to forward this data to the beneficiary to complete redemption
		return "", errors.New("Currently beneficiary must be the same as the Principal")
	}
	//restore the Seed
	_, _, ecAddPrivateKey, err := cryptowallet.Bip44Address(beneficiariesSeed, cryptowallet.CoinTypeBitcoinMain, 0, 0, 0)
	if err != nil {
		return "", err
	}
	privateKeyPart1of1 := hex.EncodeToString(ecAddPrivateKey.Serialize())
	finalPrivateKey, err := addPrivateKeys(privateKeyPart1of1, privateKeyPart2of2)
	if err != nil {
		return "", err
	}
	return finalPrivateKey, err

}

func adhocEncryptedEnvelopeEncode(s *Service, nodeID string, beneficiaryIDDocumentCID string, order documents.OrderDoc, blsSK []byte) ([]byte, error) {
	//Regenerate the original Princaipal Priv Key based on Order
	if beneficiaryIDDocumentCID == "" {
		//beneficiaryIDDocumentCID is empty when it was passed in the Inital Deposit Order
		return nil, nil
	}
	seedHex, err := common.RetrieveSeed(s.Store, order.Reference)
	if err != nil {
		return nil, err
	}
	seedOrderModifier := order.OrderDocument.OrderPart2.PreviousOrderCID
	seed, err := hex.DecodeString(seedHex)
	if err != nil {
		return nil, err
	}
	concatenatedSeeds := append(seed, seedOrderModifier...)
	finalSeed := sha256.Sum256(concatenatedSeeds)
	finalSeedHex := hex.EncodeToString(finalSeed[:])
	privateKeyPart1of2, err := cryptowallet.RedeemSecret(finalSeedHex)
	if err != nil {
		return nil, err
	}
	beneficiaryIDDocument, err := common.RetrieveIDDocFromIPFS(s.Ipfs, beneficiaryIDDocumentCID)
	if err != nil {
		return nil, err
	}
	secretBody := &documents.SimpleString{Content: privateKeyPart1of2}
	header := &documents.Header{}
	recipients := map[string]documents.IDDoc{
		beneficiaryIDDocumentCID: beneficiaryIDDocument,
	}
	docEnv, err := documents.Encode(nodeID, nil, secretBody, header, blsSK, recipients)
	if err != nil {
		return nil, err
	}
	return docEnv, err
}

func adhocEncryptedEnvelopeDecode(s *Service, sikeSK []byte, beneficiaryBlob []byte, beneficiaryIDDocumentCID string, signingBlsPK []byte) (string, error) {
	//Regenerate the original Principal Priv Key based on Order
	secretBody := &documents.SimpleString{}
	_, err := documents.Decode(beneficiaryBlob, "INTERNAL", sikeSK, beneficiaryIDDocumentCID, nil, secretBody, signingBlsPK)
	if err != nil {
		return "", err
	}
	return secretBody.Content, err
}

func generateFinalPubKey(s *Service, pubKeyPart2of2 string, order documents.OrderDoc) (string, string, error) {
	beneficiaryIDDocumentCID := order.OrderDocument.BeneficiaryCID
	coinType := order.Coin
	var pubKeyPart1of2 string

	if beneficiaryIDDocumentCID == "" {
		//There is no beneficiary ID so we do it all locally based on
		//Retrieve the Local Seed
		seedHex, err := common.RetrieveSeed(s.Store, order.Reference)
		if err != nil {
			return "", "", err
		}
		seedOrderModifier := order.OrderDocument.OrderPart2.PreviousOrderCID
		seed, err := hex.DecodeString(seedHex)
		if err != nil {
			return "", "", err
		}
		concatenatedSeeds := append(seed, seedOrderModifier...)
		finalSeed := sha256.Sum256(concatenatedSeeds)
		finalSeedHex := hex.EncodeToString(finalSeed[:])
		//Use HD Wallet to obtain the local Public Key
		pubKeyPart1of2, err = cryptowallet.RedeemPublicKey(finalSeedHex)

		if err != nil {
			return "", "", err
		}
	}

	if beneficiaryIDDocumentCID != "" {
		//There is a BeneficiaryID use it to generate the key
		//Get beneficiary's identity out of IPFS
		id := &documents.IDDoc{}
		rawDocI, err := s.Ipfs.Get(beneficiaryIDDocumentCID)
		if err != nil {
			return "", "", errors.Wrapf(err, "Read identity Doc")
		}
		err = documents.DecodeIDDocument(rawDocI, beneficiaryIDDocumentCID, id)
		if err != nil {
			return "", "", err
		}
		pubKeyPart1of2 = hex.EncodeToString(id.BeneficiaryECPublicKey)
	}

	finalPublicKey, err := addPublicKeys(pubKeyPart2of2, pubKeyPart1of2)

	if err != nil {
		return "", "", err
	}
	addressForPublicKey, err := addressForPublicKey(finalPublicKey, int(coinType))
	if err != nil {
		return "", "", err
	}
	return finalPublicKey, addressForPublicKey, nil

}

//AddPrivateKeys Perform eliptical key additon on 2 privates keys
func addPrivateKeys(key1 string, key2 string) (string, error) {
	curveOrder := new(big.Int)
	curveOrder.SetString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141", 16)
	priv1 := new(big.Int)
	priv2 := new(big.Int)
	priv3 := new(big.Int)
	priv1.SetString(key1, 16)
	priv2.SetString(key2, 16)
	priv3.Add(priv1, priv2)
	if curveOrder.Cmp(priv3) == -1 {
		priv3.Sub(priv3, curveOrder)
	}
	priv4 := fmt.Sprintf("%064x", priv3)
	return priv4, nil
}

//AddPublicKeys Perform eliptical key addition on 2 public keys
func addPublicKeys(key1 string, key2 string) (string, error) {
	pub1Hex, err := hex.DecodeString(key1)
	if err != nil {
		return "", errors.Wrap(err, "Failed to hex decode String")
	}
	dpub1, err := btcec.ParsePubKey(pub1Hex, btcec.S256())
	if err != nil {
		return "", errors.Wrap(err, "Failed to Parse Public Key")
	}
	pub2Hex, err := hex.DecodeString(key2)
	if err != nil {
		return "", errors.Wrap(err, "Failed to hex decode String")
	}
	dpub2, err := btcec.ParsePubKey(pub2Hex, btcec.S256())
	if err != nil {
		return "", errors.Wrap(err, "Failed to Parse Public Key")
	}
	x, y := btcec.S256().Add(dpub1.X, dpub1.Y, dpub2.X, dpub2.Y)
	comp := fmt.Sprintf("04%064X%064X", x, y)
	compByte, err := hex.DecodeString(comp)
	if err != nil {
		return "", err
	}
	pubKey, err := btcec.ParsePubKey([]byte(compByte), btcec.S256())
	if err != nil {
		return "", err
	}
	pubKeyString := hex.EncodeToString(pubKey.SerializeCompressed())
	return pubKeyString, nil
}
