package models

import (
	"bytes"
	"context"
	"encoding/json"
	"io"

	"github.com/aeternity/aepp-sdk-go/v8/utils"
	"github.com/go-openapi/errors"
	"github.com/go-openapi/runtime"
	"github.com/go-openapi/strfmt"
	"github.com/go-openapi/swag"
	"github.com/go-openapi/validate"
)

type ChannelForceProgressTx struct {

	ChannelID *string `json:"channel_id"`

	Fee *utils.BigInt `json:"fee"`

	FromID *string `json:"from_id"`

	Nonce uint64 `json:"nonce,omitempty"`

	OffchainTrees string `json:"offchain_trees,omitempty"`

	Payload *string `json:"payload"`

	Round *uint64 `json:"round"`

	StateHash *string `json:"state_hash"`

	TTL uint64 `json:"ttl,omitempty"`

	updateField OffChainUpdate
}

func (m *ChannelForceProgressTx) Update() OffChainUpdate {
	return m.updateField
}

func (m *ChannelForceProgressTx) SetUpdate(val OffChainUpdate) {
	m.updateField = val
}

func (m *ChannelForceProgressTx) UnmarshalJSON(raw []byte) error {
	var data struct {
		ChannelID *string `json:"channel_id"`

		Fee *utils.BigInt `json:"fee"`

		FromID *string `json:"from_id"`

		Nonce uint64 `json:"nonce,omitempty"`

		OffchainTrees string `json:"offchain_trees,omitempty"`

		Payload *string `json:"payload"`

		Round *uint64 `json:"round"`

		StateHash *string `json:"state_hash"`

		TTL uint64 `json:"ttl,omitempty"`

		Update json.RawMessage `json:"update"`
	}
	buf := bytes.NewBuffer(raw)
	dec := json.NewDecoder(buf)
	dec.UseNumber()

	if err := dec.Decode(&data); err != nil {
		return err
	}

	propUpdate, err := UnmarshalOffChainUpdate(bytes.NewBuffer(data.Update), runtime.JSONConsumer())
	if err != nil && err != io.EOF {
		return err
	}

	var result ChannelForceProgressTx

	result.ChannelID = data.ChannelID

	result.Fee = data.Fee

	result.FromID = data.FromID

	result.Nonce = data.Nonce

	result.OffchainTrees = data.OffchainTrees

	result.Payload = data.Payload

	result.Round = data.Round

	result.StateHash = data.StateHash

	result.TTL = data.TTL

	result.updateField = propUpdate

	*m = result

	return nil
}

func (m ChannelForceProgressTx) MarshalJSON() ([]byte, error) {
	var b1, b2, b3 []byte
	var err error
	b1, err = json.Marshal(struct {
		ChannelID *string `json:"channel_id"`

		Fee *utils.BigInt `json:"fee"`

		FromID *string `json:"from_id"`

		Nonce uint64 `json:"nonce,omitempty"`

		OffchainTrees string `json:"offchain_trees,omitempty"`

		Payload *string `json:"payload"`

		Round *uint64 `json:"round"`

		StateHash *string `json:"state_hash"`

		TTL uint64 `json:"ttl,omitempty"`
	}{

		ChannelID: m.ChannelID,

		Fee: m.Fee,

		FromID: m.FromID,

		Nonce: m.Nonce,

		OffchainTrees: m.OffchainTrees,

		Payload: m.Payload,

		Round: m.Round,

		StateHash: m.StateHash,

		TTL: m.TTL,
	})
	if err != nil {
		return nil, err
	}
	b2, err = json.Marshal(struct {
		Update OffChainUpdate `json:"update"`
	}{

		Update: m.updateField,
	})
	if err != nil {
		return nil, err
	}

	return swag.ConcatJSON(b1, b2, b3), nil
}

func (m *ChannelForceProgressTx) Validate(formats strfmt.Registry) error {
	var res []error

	if err := m.validateChannelID(formats); err != nil {
		res = append(res, err)
	}

	if err := m.validateFee(formats); err != nil {
		res = append(res, err)
	}

	if err := m.validateFromID(formats); err != nil {
		res = append(res, err)
	}

	if err := m.validatePayload(formats); err != nil {
		res = append(res, err)
	}

	if err := m.validateRound(formats); err != nil {
		res = append(res, err)
	}

	if err := m.validateStateHash(formats); err != nil {
		res = append(res, err)
	}

	if err := m.validateUpdate(formats); err != nil {
		res = append(res, err)
	}

	if len(res) > 0 {
		return errors.CompositeValidationError(res...)
	}
	return nil
}

func (m *ChannelForceProgressTx) validateChannelID(formats strfmt.Registry) error {

	if err := validate.Required("channel_id", "body", m.ChannelID); err != nil {
		return err
	}

	return nil
}

func (m *ChannelForceProgressTx) validateFee(formats strfmt.Registry) error {

	if err := validate.Required("fee", "body", m.Fee); err != nil {
		return err
	}

	if err := validate.Required("fee", "body", m.Fee); err != nil {
		return err
	}

	if m.Fee != nil {
		if err := m.Fee.Validate(formats); err != nil {
			if ve, ok := err.(*errors.Validation); ok {
				return ve.ValidateName("fee")
			}
			return err
		}
	}

	return nil
}

func (m *ChannelForceProgressTx) validateFromID(formats strfmt.Registry) error {

	if err := validate.Required("from_id", "body", m.FromID); err != nil {
		return err
	}

	return nil
}

func (m *ChannelForceProgressTx) validatePayload(formats strfmt.Registry) error {

	if err := validate.Required("payload", "body", m.Payload); err != nil {
		return err
	}

	return nil
}

func (m *ChannelForceProgressTx) validateRound(formats strfmt.Registry) error {

	if err := validate.Required("round", "body", m.Round); err != nil {
		return err
	}

	return nil
}

func (m *ChannelForceProgressTx) validateStateHash(formats strfmt.Registry) error {

	if err := validate.Required("state_hash", "body", m.StateHash); err != nil {
		return err
	}

	return nil
}

func (m *ChannelForceProgressTx) validateUpdate(formats strfmt.Registry) error {

	if err := validate.Required("update", "body", m.Update()); err != nil {
		return err
	}

	if err := m.Update().Validate(formats); err != nil {
		if ve, ok := err.(*errors.Validation); ok {
			return ve.ValidateName("update")
		}
		return err
	}

	return nil
}

func (m *ChannelForceProgressTx) ContextValidate(ctx context.Context, formats strfmt.Registry) error {
	var res []error

	if err := m.contextValidateFee(ctx, formats); err != nil {
		res = append(res, err)
	}

	if err := m.contextValidateUpdate(ctx, formats); err != nil {
		res = append(res, err)
	}

	if len(res) > 0 {
		return errors.CompositeValidationError(res...)
	}
	return nil
}

func (m *ChannelForceProgressTx) contextValidateFee(ctx context.Context, formats strfmt.Registry) error {

	if m.Fee != nil {
		if err := m.Fee.ContextValidate(ctx, formats); err != nil {
			if ve, ok := err.(*errors.Validation); ok {
				return ve.ValidateName("fee")
			}
			return err
		}
	}

	return nil
}

func (m *ChannelForceProgressTx) contextValidateUpdate(ctx context.Context, formats strfmt.Registry) error {

	if err := m.Update().ContextValidate(ctx, formats); err != nil {
		if ve, ok := err.(*errors.Validation); ok {
			return ve.ValidateName("update")
		}
		return err
	}

	return nil
}

func (m *ChannelForceProgressTx) MarshalBinary() ([]byte, error) {
	if m == nil {
		return nil, nil
	}
	return swag.WriteJSON(m)
}

func (m *ChannelForceProgressTx) UnmarshalBinary(b []byte) error {
	var res ChannelForceProgressTx
	if err := swag.ReadJSON(b, &res); err != nil {
		return err
	}
	*m = res
	return nil
}
// Code generated by go-swagger; DO NOT EDIT.

package models

// This file was generated by the swagger tool.
// Editing this file might prove futile when you re-run the swagger generate command

import (
	"bytes"
	"context"
	"encoding/json"
	"io"

	"github.com/aeternity/aepp-sdk-go/v8/utils"
	"github.com/go-openapi/errors"
	"github.com/go-openapi/runtime"
	"github.com/go-openapi/strfmt"
	"github.com/go-openapi/swag"
	"github.com/go-openapi/validate"
)

// ChannelForceProgressTx channel force progress tx
//
// swagger:model ChannelForceProgressTx
type ChannelForceProgressTx struct {

	// channel id
	// Required: true
	ChannelID *string `json:"channel_id"`

	// fee
	// Required: true
	Fee *utils.BigInt `json:"fee"`

	// from id
	// Required: true
	FromID *string `json:"from_id"`

	// nonce
	Nonce uint64 `json:"nonce,omitempty"`

	// The whole set of off-chain state trees
	OffchainTrees string `json:"offchain_trees,omitempty"`

	// payload
	// Required: true
	Payload *string `json:"payload"`

	// Channel's next round
	// Required: true
	Round *uint64 `json:"round"`

	// Channel's next state_hash
	// Required: true
	StateHash *string `json:"state_hash"`

	// ttl
	TTL uint64 `json:"ttl,omitempty"`

	updateField OffChainUpdate
}

// Update gets the update of this base type
func (m *ChannelForceProgressTx) Update() OffChainUpdate {
	return m.updateField
}

// SetUpdate sets the update of this base type
func (m *ChannelForceProgressTx) SetUpdate(val OffChainUpdate) {
	m.updateField = val
}

// UnmarshalJSON unmarshals this object with a polymorphic type from a JSON structure
func (m *ChannelForceProgressTx) UnmarshalJSON(raw []byte) error {
	var data struct {
		ChannelID *string `json:"channel_id"`

		Fee *utils.BigInt `json:"fee"`

		FromID *string `json:"from_id"`

		Nonce uint64 `json:"nonce,omitempty"`

		OffchainTrees string `json:"offchain_trees,omitempty"`

		Payload *string `json:"payload"`

		Round *uint64 `json:"round"`

		StateHash *string `json:"state_hash"`

		TTL uint64 `json:"ttl,omitempty"`

		Update json.RawMessage `json:"update"`
	}
	buf := bytes.NewBuffer(raw)
	dec := json.NewDecoder(buf)
	dec.UseNumber()

	if err := dec.Decode(&data); err != nil {
		return err
	}

	propUpdate, err := UnmarshalOffChainUpdate(bytes.NewBuffer(data.Update), runtime.JSONConsumer())
	if err != nil && err != io.EOF {
		return err
	}

	var result ChannelForceProgressTx

	// channel_id
	result.ChannelID = data.ChannelID

	// fee
	result.Fee = data.Fee

	// from_id
	result.FromID = data.FromID

	// nonce
	result.Nonce = data.Nonce

	// offchain_trees
	result.OffchainTrees = data.OffchainTrees

	// payload
	result.Payload = data.Payload

	// round
	result.Round = data.Round

	// state_hash
	result.StateHash = data.StateHash

	// ttl
	result.TTL = data.TTL

	// update
	result.updateField = propUpdate

	*m = result

	return nil
}

// MarshalJSON marshals this object with a polymorphic type to a JSON structure
func (m ChannelForceProgressTx) MarshalJSON() ([]byte, error) {
	var b1, b2, b3 []byte
	var err error
	b1, err = json.Marshal(struct {
		ChannelID *string `json:"channel_id"`

		Fee *utils.BigInt `json:"fee"`

		FromID *string `json:"from_id"`

		Nonce uint64 `json:"nonce,omitempty"`

		OffchainTrees string `json:"offchain_trees,omitempty"`

		Payload *string `json:"payload"`

		Round *uint64 `json:"round"`

		StateHash *string `json:"state_hash"`

		TTL uint64 `json:"ttl,omitempty"`
	}{

		ChannelID: m.ChannelID,

		Fee: m.Fee,

		FromID: m.FromID,

		Nonce: m.Nonce,

		OffchainTrees: m.OffchainTrees,

		Payload: m.Payload,

		Round: m.Round,

		StateHash: m.StateHash,

		TTL: m.TTL,
	})
	if err != nil {
		return nil, err
	}
	b2, err = json.Marshal(struct {
		Update OffChainUpdate `json:"update"`
	}{

		Update: m.updateField,
	})
	if err != nil {
		return nil, err
	}

	return swag.ConcatJSON(b1, b2, b3), nil
}

// Validate validates this channel force progress tx
func (m *ChannelForceProgressTx) Validate(formats strfmt.Registry) error {
	var res []error

	if err := m.validateChannelID(formats); err != nil {
		res = append(res, err)
	}

	if err := m.validateFee(formats); err != nil {
		res = append(res, err)
	}

	if err := m.validateFromID(formats); err != nil {
		res = append(res, err)
	}

	if err := m.validatePayload(formats); err != nil {
		res = append(res, err)
	}

	if err := m.validateRound(formats); err != nil {
		res = append(res, err)
	}

	if err := m.validateStateHash(formats); err != nil {
		res = append(res, err)
	}

	if err := m.validateUpdate(formats); err != nil {
		res = append(res, err)
	}

	if len(res) > 0 {
		return errors.CompositeValidationError(res...)
	}
	return nil
}

func (m *ChannelForceProgressTx) validateChannelID(formats strfmt.Registry) error {

	if err := validate.Required("channel_id", "body", m.ChannelID); err != nil {
		return err
	}

	return nil
}

func (m *ChannelForceProgressTx) validateFee(formats strfmt.Registry) error {

	if err := validate.Required("fee", "body", m.Fee); err != nil {
		return err
	}

	if err := validate.Required("fee", "body", m.Fee); err != nil {
		return err
	}

	if m.Fee != nil {
		if err := m.Fee.Validate(formats); err != nil {
			if ve, ok := err.(*errors.Validation); ok {
				return ve.ValidateName("fee")
			}
			return err
		}
	}

	return nil
}

func (m *ChannelForceProgressTx) validateFromID(formats strfmt.Registry) error {

	if err := validate.Required("from_id", "body", m.FromID); err != nil {
		return err
	}

	return nil
}

func (m *ChannelForceProgressTx) validatePayload(formats strfmt.Registry) error {

	if err := validate.Required("payload", "body", m.Payload); err != nil {
		return err
	}

	return nil
}

func (m *ChannelForceProgressTx) validateRound(formats strfmt.Registry) error {

	if err := validate.Required("round", "body", m.Round); err != nil {
		return err
	}

	return nil
}

func (m *ChannelForceProgressTx) validateStateHash(formats strfmt.Registry) error {

	if err := validate.Required("state_hash", "body", m.StateHash); err != nil {
		return err
	}

	return nil
}

func (m *ChannelForceProgressTx) validateUpdate(formats strfmt.Registry) error {

	if err := validate.Required("update", "body", m.Update()); err != nil {
		return err
	}

	if err := m.Update().Validate(formats); err != nil {
		if ve, ok := err.(*errors.Validation); ok {
			return ve.ValidateName("update")
		}
		return err
	}

	return nil
}

// ContextValidate validate this channel force progress tx based on the context it is used
func (m *ChannelForceProgressTx) ContextValidate(ctx context.Context, formats strfmt.Registry) error {
	var res []error

	if err := m.contextValidateFee(ctx, formats); err != nil {
		res = append(res, err)
	}

	if err := m.contextValidateUpdate(ctx, formats); err != nil {
		res = append(res, err)
	}

	if len(res) > 0 {
		return errors.CompositeValidationError(res...)
	}
	return nil
}

func (m *ChannelForceProgressTx) contextValidateFee(ctx context.Context, formats strfmt.Registry) error {

	if m.Fee != nil {
		if err := m.Fee.ContextValidate(ctx, formats); err != nil {
			if ve, ok := err.(*errors.Validation); ok {
				return ve.ValidateName("fee")
			}
			return err
		}
	}

	return nil
}

func (m *ChannelForceProgressTx) contextValidateUpdate(ctx context.Context, formats strfmt.Registry) error {

	if err := m.Update().ContextValidate(ctx, formats); err != nil {
		if ve, ok := err.(*errors.Validation); ok {
			return ve.ValidateName("update")
		}
		return err
	}

	return nil
}

// MarshalBinary interface implementation
func (m *ChannelForceProgressTx) MarshalBinary() ([]byte, error) {
	if m == nil {
		return nil, nil
	}
	return swag.WriteJSON(m)
}

// UnmarshalBinary interface implementation
func (m *ChannelForceProgressTx) UnmarshalBinary(b []byte) error {
	var res ChannelForceProgressTx
	if err := swag.ReadJSON(b, &res); err != nil {
		return err
	}
	*m = res
	return nil
}
