//! The type that represents a block element.
//!
//! <https://api.slack.com/reference/block-kit/block-elements>
//!
//! This crate only supports `Button` now.

use crate::ConfirmObect;
use crate::TextObject;
use serde::Serialize;

/// A unique identifier for an action.
#[derive(Serialize, Debug, Clone)]
pub struct ActionId(pub String);

/// The type that represents a block element.
///
/// <https://api.slack.com/reference/block-kit/block-elements>
///
/// This crate only supports `Button` now.
#[derive(Serialize, Debug, Clone)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum Element {
    /// Button element.
    ///
    /// <https://api.slack.com/reference/block-kit/block-elements#button>
    Button(ButtonElement),
}

/// Button element.
///
/// <https://api.slack.com/reference/block-kit/block-elements#button>
#[derive(Serialize, Debug, Clone)]
#[serde(rename_all = "snake_case")]
pub struct ButtonElement {
    /// A [text object](https://api.slack.com/reference/block-kit/composition-objects#text) that defines the button's text.
    pub text: TextObject,

    /// An identifier for this action.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub action_id: Option<ActionId>,

    /// A URL to load in the user's browser when the button is clicked.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub url: Option<String>,

    /// The value to send along with the [interaction payload](https://api.slack.com/interactivity/handling#payloads).
    #[serde(skip_serializing_if = "Option::is_none")]
    pub value: Option<String>,

    /// `primary` gives buttons a green outline and text, ideal for affirmation or confirmation actions.
    #[serde(skip_serializing_if = "ButtonStyle::is_default")]
    pub style: ButtonStyle,

    /// A [confirm object](https://api.slack.com/reference/block-kit/composition-objects#confirm) that defines an optional confirmation dialog after the button is clicked.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub confirm: Option<ConfirmObect>,
    // accessibility_label: Option<String>,
}

/// The enumerated value that represents the button style.
#[derive(Serialize, Debug, Clone)]
#[serde(rename_all = "lowercase")]
pub enum ButtonStyle {
    /// No value in the field.
    Default,

    /// `primary` gives buttons a green outline and text, ideal for affirmation or confirmation actions.
    Primary,

    /// `danger` gives buttons a red outline and text, and should be used when the action is destructive.
    Danger,
}

impl ButtonStyle {
    /// Returns true if the [`ButtonStyle`] is [`ButtonStyle::Default`].
    pub fn is_default(&self) -> bool {
        matches!(self, ButtonStyle::Default)
    }
}
