// 

import bcoin from 'bcoin'

const changeAddressPrefix = (
  address,
  newPrefix,
  expectedPrefix
) => {
  const prefix = address.getPrefix()
  if (prefix !== expectedPrefix) return null
  const bw = new bcoin.utils.StaticWriter(address.getSize())
  bw.writeU8(newPrefix)
  if (address.version !== -1) {
    bw.writeU8(address.version)
    bw.writeU8(0)
  }
  bw.writeBytes(address.hash)
  bw.writeChecksum()
  return bcoin.utils.base58.encode(bw.render())
}

const getPrefixes = (addressObj, addressPrefix) => {
  const type = addressObj.getType()
  if (addressPrefix[`${type}Legacy`] === undefined) return {}
  return {
    legacyPrefix: addressPrefix[`${type}Legacy`],
    newPrefix: addressPrefix[`${type}`]
  }
}

export const toLegacyFormat = (address, network) => {
  const { serializers = {}, addressPrefix = {} } = bcoin.networks[network] || {}
  try {
    const addressToDecode = serializers.address
      ? serializers.address.decode(address)
      : address
    const addressObj = bcoin.primitives.Address.fromBase58(
      addressToDecode,
      network
    )
    const { legacyPrefix, newPrefix } = getPrefixes(addressObj, addressPrefix)
    return changeAddressPrefix(addressObj, legacyPrefix, newPrefix) || address
  } catch (e) {
    return address
  }
}

export const toNewFormat = (address, network) => {
  const { serializers = {}, addressPrefix = {} } = bcoin.networks[network] || {}
  let newAddress = address
  try {
    if (serializers.address) {
      newAddress = serializers.address.decode(newAddress)
    }

    const addressObj = bcoin.primitives.Address.fromBase58(newAddress)
    const { legacyPrefix, newPrefix } = getPrefixes(addressObj, addressPrefix)

    if (legacyPrefix) {
      const changedAddress = changeAddressPrefix(
        addressObj,
        newPrefix,
        legacyPrefix
      )
      if (changedAddress) {
        newAddress = changedAddress
      }
    }
  } catch (e) {}

  try {
    if (serializers.address) {
      newAddress = serializers.address.encode(newAddress)
    }
  } catch (e) {}

  return newAddress
}

export const validAddress = (address, network) => {
  const { addressPrefix = {}, serializers = {} } = bcoin.networks[network] || {}
  try {
    if (serializers.address) address = serializers.address.decode(address)
    // verify address for base58 format
    const prefix = bcoin.primitives.Address.fromBase58(
      address,
      network
    ).getPrefix()
    const { pubkeyhash, scripthash } = addressPrefix
    if (prefix !== pubkeyhash && prefix !== scripthash) return false
  } catch (e) {
    try {
      // verify address for bech32 format
      const hrp = bcoin.utils.bech32.decode(address).hrp
      const { bech32 } = addressPrefix
      if (hrp !== bech32) return false
    } catch (e) {
      return false
    }
  }
  return true
}
