//! `Group` type.

use crate::durandal::err::*;
use bitflags::bitflags;

/// Reads an `InterGroup`.
pub fn read(b: &[u8]) -> ResultS<(InterGroup, usize)>
{
   read_data! {
      endian: BIG, buf: b, size: 12, start: 0, data {
         let flags = u16[0] flag GroupFlags;
         let ttype = u16[2];
         let pdata = u16[4];
         let beg   = u16[6] usize;
         let len   = u16[8] usize;
         let lines = u16[10];
      }
   }

   let ttype = match ttype {
      0  => GroupType::Logon(pdata),
      1  => GroupType::Unfinished,
      2  => GroupType::Success,
      3  => GroupType::Failure,
      4  => GroupType::Info,
      5  => GroupType::End,
      6  => GroupType::TeleInter(pdata),
      7  => GroupType::TeleIntra(pdata),
      8  => GroupType::Checkpoint(pdata),
      9  => GroupType::Sound(pdata),
      10 => GroupType::Movie(pdata),
      11 => GroupType::Track(pdata),
      12 => GroupType::Pict(pdata),
      13 => GroupType::Logoff(pdata),
      14 => GroupType::Camera(pdata),
      15 => GroupType::Static(pdata),
      16 => GroupType::Tag(pdata),
      n  => return Err(ReprError::new(n).into()),
   };

   Ok((InterGroup{flags, ttype, lines, beg, len}, 12))
}

impl Default for GroupType
{
   fn default() -> Self {GroupType::Unfinished}
}

/// Interim structure.
#[derive(Debug, Eq, PartialEq)]
pub struct InterGroup
{
   pub flags: GroupFlags,
   pub ttype: GroupType,
   pub lines: u16,
   pub beg:   usize,
   pub len:   usize,
}

/// A terminal command grouping.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
#[derive(Debug, Eq, PartialEq)]
pub struct Group
{
   pub flags: GroupFlags,
   pub ttype: GroupType,
   pub lines: u16,
   pub text:  String,
}

/// The command of a `Group`.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum GroupType
{
   Logon(u16),
   Unfinished,
   Success,
   Failure,
   Info,
   End,
   TeleInter(u16),
   TeleIntra(u16),
   Checkpoint(u16),
   Sound(u16),
   Movie(u16),
   Track(u16),
   Pict(u16),
   Logoff(u16),
   Camera(u16),
   Static(u16),
   Tag(u16),
}

bitflags! {
   /// Flags for `Group`.
   #[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
   pub struct GroupFlags: u16
   {
      /// Draws the picture on the right.
      const DRAW_ON_RIGHT = 1;
      /// Draws the picture in the center.
      const DRAW_CENTER   = 1 << 1;
   }
}

// EOF
