mcai-backend 0.0.1

CLI tool for the Media Cloud AI Backend
use crate::{constants::*, models::*, Error, Result};
use reqwest::{blocking::Response, Method};
use std::{convert::TryFrom, str::FromStr};

#[derive(Debug)]
pub enum Action {
  WorkflowDefinitions,
  WorkflowDefinition(String),
  WorkerDefinitions,
  WorkerDefinition(usize),
  Workflows,
  Workflow(usize),
  Unknown,
}

impl Action {
  pub fn get_method(&self) -> Method {
    match self {
      Action::Workflows
      | Action::WorkerDefinitions
      | Action::WorkflowDefinitions
      | Action::Workflow(_)
      | Action::WorkerDefinition(_)
      | Action::WorkflowDefinition(_) => Method::GET,
      Action::Unknown => unreachable!(),
    }
  }

  pub fn get_url(&self) -> String {
    let endpoint = match self {
      Action::Workflows => "/workflows".to_string(),
      Action::WorkerDefinitions => "/worker_definitions".to_string(),
      Action::WorkflowDefinitions => "/definitions".to_string(),
      Action::Workflow(identifier) => format!("/workflows/{}", identifier),
      Action::WorkerDefinition(identifier) => format!("/worker_definitions/{}", identifier),
      Action::WorkflowDefinition(identifier) => format!("/definitions/{}", identifier),
      Action::Unknown => unreachable!(),
    };

    format!("/api/step_flow{}", endpoint)
  }

  pub fn format_output(&self, response: Response) -> Result<()> {
    match self {
      Action::Workflows => {
        let workflows: WorkflowsData = response.json()?;
        workflows.render();
      }
      Action::Workflow(_) => {
        let workflow: WorkflowData = response.json()?;
        workflow.render();
      }
      Action::WorkerDefinitions => {
        let workers: WorkerDefinitionsData = response.json()?;
        workers.render();
      }
      Action::WorkerDefinition(_) => {
        let worker: WorkerDefinitionData = response.json()?;
        worker.render();
      }
      Action::Unknown => unreachable!(),
      _ => {}
    };
    Ok(())
  }
}

impl<'a> TryFrom<&clap::ArgMatches<'a>> for Action {
  type Error = crate::Error;

  fn try_from(matches: &clap::ArgMatches<'a>) -> std::result::Result<Self, Self::Error> {
    let action = match matches.subcommand() {
      (label, Some(_)) if label == SUBCOMMAND_WORKFLOW_DEFINITIONS => Action::WorkflowDefinitions,
      (label, Some(_)) if label == SUBCOMMAND_WORKER_DEFINITIONS => Action::WorkerDefinitions,
      (label, Some(_)) if label == SUBCOMMAND_WORKFLOWS => Action::Workflows,

      (label, Some(matches)) if label == SUBCOMMAND_WORKFLOW_DEFINITION => {
        let identifier = get_identifier(matches)?;
        Action::WorkerDefinition(identifier)
      }
      (label, Some(matches)) if label == SUBCOMMAND_WORKER_DEFINITION => {
        let identifier = get_string_identifier(matches)?;
        Action::WorkflowDefinition(identifier)
      }
      (label, Some(matches)) if label == SUBCOMMAND_WORKFLOW => {
        let identifier = get_identifier(matches)?;
        Action::Workflow(identifier)
      }
      _ => Action::Unknown,
    };

    Ok(action)
  }
}

fn get_identifier(matches: &clap::ArgMatches<'_>) -> Result<usize> {
  matches
    .value_of(PARAMETER_IDENTIFIER)
    .map(|value| usize::from_str(value).unwrap())
    .ok_or_else(|| Error::MissingParameter(PARAMETER_IDENTIFIER.to_string()))
}

fn get_string_identifier(matches: &clap::ArgMatches<'_>) -> Result<String> {
  matches
    .value_of(PARAMETER_IDENTIFIER)
    .map(|value| value.to_owned())
    .ok_or_else(|| Error::MissingParameter(PARAMETER_IDENTIFIER.to_string()))
}