package foundation.omni.json.pojo;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import foundation.omni.CurrencyID;
import foundation.omni.OmniValue;
import foundation.omni.net.OmniMainNetParams;
import foundation.omni.rpc.SmartPropertyListInfo;
import org.bitcoinj.core.Address;
import org.bitcoinj.core.LegacyAddress;
import org.bitcoinj.core.Sha256Hash;
import org.bitcoinj.params.MainNetParams;

import java.math.BigDecimal;

/**
 * JSON bean representing the set of information on an Omni Property as returned by the
 * {@code omni_getproperty} RPC method. It is a subclass of {@link SmartPropertyListInfo}
 * because it is a superset of that information.
 */
public class OmniPropertyInfo extends SmartPropertyListInfo {
    private final Address issuer;
    private final Sha256Hash creationtxid;
    private final boolean fixedissuance;
    private final boolean managedissuance;
    private final boolean freezingenabled;
    private final OmniValue totaltokens;

    @JsonCreator
    public OmniPropertyInfo(@JsonProperty("propertyid") CurrencyID propertyid,
                            @JsonProperty("name") String name,
                            @JsonProperty("category") String category,
                            @JsonProperty("subCategory") String subCategory,
                            @JsonProperty("data") String data,
                            @JsonProperty("url") String url,
                            @JsonProperty("divisible") Boolean divisible,
                            @JsonProperty("issuer") Address issuer,
                            @JsonProperty("creationtxid") Sha256Hash creationTxId,
                            @JsonProperty("fixedissuance") boolean fixedIssuance,
                            @JsonProperty("managedissuance") boolean managedIssuance,
                            @JsonProperty("freezingenabled") boolean freezingEnabled,
                            @JsonProperty("totaltokens") String totaltokensString) {
        this(propertyid,
                name,
                category,
                subCategory,
                data,
                url,
                divisible,
                issuer,
                creationTxId,
                fixedIssuance,
                managedIssuance,
                freezingEnabled,
                OmniValue.of(new BigDecimal(totaltokensString), divisible));
    }

    public OmniPropertyInfo(CurrencyID propertyid,
                            String name,
                            String category,
                            String subCategory,
                            String data,
                            String url,
                            Boolean divisible,
                            Address issuer,
                            Sha256Hash creationTxId,
                            boolean fixedIssuance,
                            boolean managedIssuance,
                            boolean freezingEnabled,
                            OmniValue totalTokens) {
        super(propertyid, name, category, subCategory, data, url, divisible);
        this.issuer = issuer;
        this.creationtxid = creationTxId;
        this.fixedissuance = fixedIssuance;
        this.managedissuance = managedIssuance;
        this.freezingenabled = freezingEnabled;
        this.totaltokens = totalTokens;
    }

    /**
     * Construct OmniPropertyInfo from SmartPropertyListInfo
     * Since there is no way to fetch OmniPropertyInfo for all properties with a
     * single request, this converter can be used to create a OmniPropertyInfo
     * from a SmartPropertyListInfo with default values for the extra fields.
     * TODO: Address the fact that (in this case) we really don't have all the info and the default
     *       values we are using are potentially incorrect
     * TODO: Figure out a way of efficiently getting OmniPropertyInfo for all properties.
     *
     * @param sptListInfo record to adapt
     */
    public OmniPropertyInfo(SmartPropertyListInfo sptListInfo) {
        super(sptListInfo.getPropertyid(),
                sptListInfo.getName(),
                sptListInfo.getCategory(),
                sptListInfo.getSubcategory(),
                sptListInfo.getData(),
                sptListInfo.getUrl(),
                sptListInfo.getDivisible());
        this.issuer = null;                             // Issuer unknown
        this.creationtxid = null;                       // Creation Tx unknown
        this.fixedissuance = false;                     // Not nullable so use `false`
        this.managedissuance = false;                   // Not nullable so use `false`
        this.freezingenabled = false;                   // Not nullable so use `false`
        this.totaltokens = OmniValue.ofWilletts(0, sptListInfo.getDivisible());
    }

    public Address getIssuer() {
        return issuer;
    }

    public Sha256Hash getCreationtxid() {
        return creationtxid;
    }

    public boolean isFixedissuance() {
        return fixedissuance;
    }

    public boolean isManagedissuance() {
        return managedissuance;
    }

    public boolean isFreezingenabled() {
        return freezingenabled;
    }

    public OmniValue getTotaltokens() {
        return totaltokens;
    }

    /**
     * Return a <i>mock</i> {@code OmniPropertyInfo} for Bitcoin. Many of the fields are "n/a" and
     * we give the final, total number of tokens, not the current, dynamic value. This is useful
     * in cases where we need Bitcoin in the list of tokens, but don't have access to current
     * Bitcoin data. OmniProxy is able to provide accurate, dynamic information so does not
     * use this mock value.
     *
     * @return static (mock) info for Bitcoin
     */
    public static OmniPropertyInfo mockBitcoinPropertyInfo() {
        return new OmniPropertyInfo(CurrencyID.BTC,
                "Bitcoin",
                "n/a",
                "n/a",
                "n/a",
                "n/a",
                true,
                LegacyAddress.fromBase58(MainNetParams.get(), "1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa"),
                Sha256Hash.ZERO_HASH,
                false,
                false,
                false,
                "21000000.00000000");
    }
}

@@ -171,16 +171,59 @@
 encyID;%0A
+import foundation.omni.OmniDivisibleValue;%0A
 import f
@@ -370,32 +370,63 @@
 j.core.Address;%0A
+import org.bitcoinj.core.Coin;%0A
 import org.bitco
@@ -5923,24 +5923,535 @@
 rtyInfo() %7B%0A
+        return bitcoinPropertyInfo(Coin.COIN.multiply(21_000_000));%0A    %7D%0A%0A    /**%0A     * Return %7B@code OmniPropertyInfo%7D for Bitcoin. Many of the fields are %22n/a%22 but%0A     * we give current, dynamic count of bitcoins. This method is used%0A     * by %3Cb%3EOmniProxy%3C/b%3E with the current count of coins from %7B@link org.consensusj.bitcoin.json.pojo.TxOutSetInfo%7D.%0A     *%0A     * @return info for Bitcoin with current number of coins%0A     */%0A    public static OmniPropertyInfo bitcoinPropertyInfo(Coin bitcoinSupply) %7B%0A
         retu
@@ -6490,16 +6490,16 @@
 ID.BTC,%0A
-
         
@@ -6859,27 +6859,63 @@
     
-%2221000000.00000000%22
+OmniDivisibleValue.ofWilletts(bitcoinSupply.getValue())
 );%0A 

add bitcoinPropertyInfo() with Coin parameter