import opcodes::*;

export struct Remark {
    opcode = REMARK,
    ...rest: Any = nil,
}

export struct AggSigParent {
    opcode = AGG_SIG_PARENT,
    public_key: PublicKey,
    message: Bytes,
}

export struct AggSigPuzzle {
    opcode = AGG_SIG_PUZZLE,
    public_key: PublicKey,
    message: Bytes,
}

export struct AggSigAmount {
    opcode = AGG_SIG_AMOUNT,
    public_key: PublicKey,
    message: Bytes,
}

export struct AggSigPuzzleAmount {
    opcode = AGG_SIG_PUZZLE_AMOUNT,
    public_key: PublicKey,
    message: Bytes,
}

export struct AggSigParentAmount {
    opcode = AGG_SIG_PARENT_AMOUNT,
    public_key: PublicKey,
    message: Bytes,
}

export struct AggSigParentPuzzle {
    opcode = AGG_SIG_PARENT_PUZZLE,
    public_key: PublicKey,
    message: Bytes,
}

export struct AggSigUnsafe {
    opcode = AGG_SIG_UNSAFE,
    public_key: PublicKey,
    message: Bytes,
}

export struct AggSigMe {
    opcode = AGG_SIG_ME,
    public_key: PublicKey,
    message: Bytes,
}

export struct CreateCoin {
    opcode = CREATE_COIN,
    puzzle_hash: Bytes32,
    amount: Int,
    ...memos: Memos | nil = nil,
}

export struct Memos {
    value: Any,
}

export struct ReserveFee {
    opcode = RESERVE_FEE,
    amount: Int,
}

export struct CreateCoinAnnouncement {
    opcode = CREATE_COIN_ANNOUNCEMENT,
    message: Bytes,
}

export struct AssertCoinAnnouncement {
    opcode = ASSERT_COIN_ANNOUNCEMENT,
    id: Bytes32,
}

export struct CreatePuzzleAnnouncement {
    opcode = CREATE_PUZZLE_ANNOUNCEMENT,
    message: Bytes,
}

export struct AssertPuzzleAnnouncement {
    opcode = ASSERT_PUZZLE_ANNOUNCEMENT,
    id: Bytes32,
}

export struct AssertConcurrentSpend {
    opcode = ASSERT_CONCURRENT_SPEND,
    coin_id: Bytes32,
}

export struct AssertConcurrentPuzzle {
    opcode = ASSERT_CONCURRENT_PUZZLE,
    puzzle_hash: Bytes32,
}

export struct SendMessage {
    opcode = SEND_MESSAGE,
    mode: Int,
    message: Bytes,
    ...receiver: List<Bytes | Int>,
}

export struct ReceiveMessage {
    opcode = RECEIVE_MESSAGE,
    mode: Int,
    message: Bytes,
    ...sender: List<Bytes | Int>,
}

export struct AssertMyCoinId {
    opcode = ASSERT_MY_COIN_ID,
    coin_id: Bytes32,
}

export struct AssertMyParentId {
    opcode = ASSERT_MY_PARENT_ID,
    parent_id: Bytes32,
}

export struct AssertMyPuzzleHash {
    opcode = ASSERT_MY_PUZZLE_HASH,
    puzzle_hash: Bytes32,
}

export struct AssertMyAmount {
    opcode = ASSERT_MY_AMOUNT,
    amount: Int,
}

export struct AssertMyBirthSeconds {
    opcode = ASSERT_MY_BIRTH_SECONDS,
    seconds: Int,
}

export struct AssertMyBirthHeight {
    opcode = ASSERT_MY_BIRTH_HEIGHT,
    height: Int,
}

export struct AssertEphemeral {
    opcode = ASSERT_EPHEMERAL,
}

export struct AssertSecondsRelative {
    opcode = ASSERT_SECONDS_RELATIVE,
    seconds: Int,
}

export struct AssertSecondsAbsolute {
    opcode = ASSERT_SECONDS_ABSOLUTE,
    seconds: Int,
}

export struct AssertHeightRelative {
    opcode = ASSERT_HEIGHT_RELATIVE,
    height: Int,
}

export struct AssertHeightAbsolute {
    opcode = ASSERT_HEIGHT_ABSOLUTE,
    height: Int,
}

export struct AssertBeforeSecondsRelative {
    opcode = ASSERT_BEFORE_SECONDS_RELATIVE,
    seconds: Int,
}

export struct AssertBeforeSecondsAbsolute {
    opcode = ASSERT_BEFORE_SECONDS_ABSOLUTE,
    seconds: Int,
}

export struct AssertBeforeHeightRelative {
    opcode = ASSERT_BEFORE_HEIGHT_RELATIVE,
    height: Int,
}

export struct AssertBeforeHeightAbsolute {
    opcode = ASSERT_BEFORE_HEIGHT_ABSOLUTE,
    height: Int,
}

export struct Softfork {
    opcode = SOFTFORK,
    cost: Int,
    ...args: List<Any>,
}

export type Condition =
    Remark | AggSigParent | AggSigPuzzle | AggSigAmount
    | AggSigPuzzleAmount | AggSigParentAmount | AggSigParentPuzzle
    | AggSigUnsafe | AggSigMe | CreateCoin | ReserveFee
    | CreateCoinAnnouncement | AssertCoinAnnouncement
    | CreatePuzzleAnnouncement | AssertPuzzleAnnouncement
    | AssertConcurrentSpend | AssertConcurrentPuzzle
    | SendMessage | ReceiveMessage | AssertMyCoinId | AssertMyParentId
    | AssertMyPuzzleHash | AssertMyAmount | AssertMyBirthSeconds
    | AssertMyBirthHeight | AssertEphemeral | AssertSecondsRelative
    | AssertSecondsAbsolute | AssertHeightRelative | AssertHeightAbsolute
    | AssertBeforeSecondsRelative | AssertBeforeSecondsAbsolute
    | AssertBeforeHeightRelative | AssertBeforeHeightAbsolute
    | Softfork;
