<commit_before># require 'yaml'
require 'io/console'
require 'rest_client'
require 'optparse'
require 'filesize'
require 'morpheus/cli/cli_command'
#require 'morpheus/cli/mixins/infrastructure_helper'

class Morpheus::Cli::Clusters
  include Morpheus::Cli::CliCommand
  include Morpheus::Cli::ProvisioningHelper
  include Morpheus::Cli::WhoamiHelper
  include Morpheus::Cli::AccountsHelper

  register_subcommands :list, :count, :get, :view, :add, :update, :remove
  
  def connect(opts)
    @api_client = establish_remote_appliance_connection(opts)
    @clusters_interface = @api_client.clusters
    @groups_interface = @api_client.groups
    @compute_type_layouts_interface = @api_client.library_compute_type_layouts
    @security_groups_interface = @api_client.security_groups
    #@security_group_rules_interface = @api_client.security_group_rules
    @cloud_resource_pools_interface = @api_client.cloud_resource_pools
    @clouds_interface = @api_client.clouds
    @servers_interface = @api_client.servers
    @server_types_interface = @api_client.server_types
    @options_interface = @api_client.options
    @active_group_id = Morpheus::Cli::Groups.active_group
    @provision_types_interface = @api_client.provision_types
    @user_groups_interface = @api_client.user_groups
    #@active_security_group = ::Morpheus::Cli::SecurityGroups.load_security_group_file
  end

  def handle(args)
    handle_subcommand(args)
  end

  def list(args)
    options = {}
    optparse = Morpheus::Cli::OptionParser.new do |opts|
      opts.banner = subcommand_usage()
      build_common_options(opts, options, [:list, :query, :json, :yaml, :csv, :fields, :dry_run, :remote])
      opts.footer = "List clusters."
    end
    optparse.parse!(args)
    if args.count != 0
      raise_command_error "wrong number of arguments, expected 0 and got (#{args.count}) #{args.join(' ')}\n#{optparse}"
    end
    connect(options)
    begin
      params = {}
      params.merge!(parse_list_options(options))
      @clusters_interface.setopts(options)
      if options[:dry_run]
        print_dry_run @clusters_interface.dry.list(params)
        return
      end
      json_response = @clusters_interface.list(params)
      
      render_result = render_with_format(json_response, options, 'clusters')
      return 0 if render_result

      title = "Morpheus Clusters"
      subtitles = []
      subtitles += parse_list_subtitles(options)
      print_h1 title, subtitles

      clusters = json_response['clusters']
      
      if clusters.empty?
        print yellow,"No clusters found.",reset,"\n"
      else
        print_clusters_table(clusters, options)
      end
      print reset,"\n"
      return 0
    rescue RestClient::Exception => e
      print_rest_exception(e, options)
      exit 1
    end
  end

  def count(args)
    options = {}
    optparse = Morpheus::Cli::OptionParser.new do |opts|
      opts.banner = subcommand_usage("[options]")
      build_common_options(opts, options, [:query, :remote, :dry_run])
      opts.footer = "Get the number of clusters."
    end
    optparse.parse!(args)
    connect(options)
    begin
      params = {}
      params.merge!(parse_list_options(options))
      @clusters_interface.setopts(options)
      if options[:dry_run]
        print_dry_run @clusters_interface.dry.get(params)
        return
      end
      json_response = @clusters_interface.get(params)
      # print number only
      if json_response['meta'] && json_response['meta']['total']
        print cyan, json_response['meta']['total'], reset, "\n"
      else
        print yellow, "unknown", reset, "\n"
      end
    rescue RestClient::Exception => e
      print_rest_exception(e, options)
      exit 1
    end
  end

  def get(args)
    options = {}
    optparse = Morpheus::Cli::OptionParser.new do |opts|
      opts.banner = subcommand_usage("[id]")
      opts.on('--refresh [SECONDS]', String, "Refresh until status is provisioned,failed. Default interval is #{default_refresh_interval} seconds.") do |val|
        options[:refresh_until_status] ||= "provisioned,failed"
        if !val.to_s.empty?
          options[:refresh_interval] = val.to_f
        end
      end
      opts.on('--refresh-until STATUS', String, "Refresh until a specified status is reached.") do |val|
        options[:refresh_until_status] = val.to_s.downcase
      end
      build_common_options(opts, options, [:json, :dry_run, :remote])
      opts.footer = "Get details about a cluster."
    end
    optparse.parse!(args)
    if args.count < 1
      puts optparse
      exit 1
    end
    connect(options)
    id_list = parse_id_list(args)
    return run_command_for_each_arg(id_list) do |arg|
      _get(arg, options)
    end
  end

  def _get(arg, options={})
    
    begin
      @clusters_interface.setopts(options)

      if options[:dry_run]
        if arg.to_s =~ /\A\d{1,}\Z/
          print_dry_run @clusters_interface.dry.get(arg.to_i)
        else
          print_dry_run @clusters_interface.dry.list({name:arg})
        end
        return 0
      end
      cluster = find_cluster_by_name_or_id(arg)
      return 1 if cluster.nil?
      json_response = nil
      if arg.to_s =~ /\A\d{1,}\Z/
        json_response = {'cluster' => cluster}  # skip redundant request
      else
        json_response = @clusters_interface.get(cluster['id'])
      end

      if options[:json]
        print JSON.pretty_generate(json_response)
        print "\n"
        return
      end

      cluster = json_response['cluster']
      worker_stats = cluster['workerStats']
      clusterType = find_cluster_type_by_id(cluster['type']['id'])

      print_h1 "Morpheus Cluster"
      print cyan
      description_cols = {
          "ID" => 'id',
          "Name" => 'name',
          "Type" => lambda { |it| it['type']['name'] },
          "Code" => 'code',
          "Group" => lambda { |it| it['site']['name'] },
          "Cloud" => lambda { |it| it['zone']['name'] },
          "Visibility" => lambda { |it| it['visibility'].to_s.capitalize },
          #"Groups" => lambda {|it| it['groups'].collect {|g| g.instance_of?(Hash) ? g['name'] : g.to_s }.join(', ') },
          #"Owner" => lambda {|it| it['owner'].instance_of?(Hash) ? it['owner']['name'] : it['ownerId'] },
          #"Tenant" => lambda {|it| it['account'].instance_of?(Hash) ? it['account']['name'] : it['accountId'] },
          "Created By" => lambda {|it| it['createdBy'] ? it['createdBy']['username'] : '' },
          "Enabled" => lambda { |it| format_boolean(it['enabled']) },
          "Status" => lambda { |it| format_cluster_status(it) }
      }
      print_description_list(description_cols, cluster)

      print_h2 "Cluster Details"
      print cyan<commit_msg>clusters get should show Location too<commit_after># require 'yaml'
require 'io/console'
require 'rest_client'
require 'optparse'
require 'filesize'
require 'morpheus/cli/cli_command'
#require 'morpheus/cli/mixins/infrastructure_helper'

class Morpheus::Cli::Clusters
  include Morpheus::Cli::CliCommand
  include Morpheus::Cli::ProvisioningHelper
  include Morpheus::Cli::WhoamiHelper
  include Morpheus::Cli::AccountsHelper

  register_subcommands :list, :count, :get, :view, :add, :update, :remove
  
  def connect(opts)
    @api_client = establish_remote_appliance_connection(opts)
    @clusters_interface = @api_client.clusters
    @groups_interface = @api_client.groups
    @compute_type_layouts_interface = @api_client.library_compute_type_layouts
    @security_groups_interface = @api_client.security_groups
    #@security_group_rules_interface = @api_client.security_group_rules
    @cloud_resource_pools_interface = @api_client.cloud_resource_pools
    @clouds_interface = @api_client.clouds
    @servers_interface = @api_client.servers
    @server_types_interface = @api_client.server_types
    @options_interface = @api_client.options
    @active_group_id = Morpheus::Cli::Groups.active_group
    @provision_types_interface = @api_client.provision_types
    @user_groups_interface = @api_client.user_groups
    #@active_security_group = ::Morpheus::Cli::SecurityGroups.load_security_group_file
  end

  def handle(args)
    handle_subcommand(args)
  end

  def list(args)
    options = {}
    optparse = Morpheus::Cli::OptionParser.new do |opts|
      opts.banner = subcommand_usage()
      build_common_options(opts, options, [:list, :query, :json, :yaml, :csv, :fields, :dry_run, :remote])
      opts.footer = "List clusters."
    end
    optparse.parse!(args)
    if args.count != 0
      raise_command_error "wrong number of arguments, expected 0 and got (#{args.count}) #{args.join(' ')}\n#{optparse}"
    end
    connect(options)
    begin
      params = {}
      params.merge!(parse_list_options(options))
      @clusters_interface.setopts(options)
      if options[:dry_run]
        print_dry_run @clusters_interface.dry.list(params)
        return
      end
      json_response = @clusters_interface.list(params)
      
      render_result = render_with_format(json_response, options, 'clusters')
      return 0 if render_result

      title = "Morpheus Clusters"
      subtitles = []
      subtitles += parse_list_subtitles(options)
      print_h1 title, subtitles

      clusters = json_response['clusters']
      
      if clusters.empty?
        print yellow,"No clusters found.",reset,"\n"
      else
        print_clusters_table(clusters, options)
      end
      print reset,"\n"
      return 0
    rescue RestClient::Exception => e
      print_rest_exception(e, options)
      exit 1
    end
  end

  def count(args)
    options = {}
    optparse = Morpheus::Cli::OptionParser.new do |opts|
      opts.banner = subcommand_usage("[options]")
      build_common_options(opts, options, [:query, :remote, :dry_run])
      opts.footer = "Get the number of clusters."
    end
    optparse.parse!(args)
    connect(options)
    begin
      params = {}
      params.merge!(parse_list_options(options))
      @clusters_interface.setopts(options)
      if options[:dry_run]
        print_dry_run @clusters_interface.dry.get(params)
        return
      end
      json_response = @clusters_interface.get(params)
      # print number only
      if json_response['meta'] && json_response['meta']['total']
        print cyan, json_response['meta']['total'], reset, "\n"
      else
        print yellow, "unknown", reset, "\n"
      end
    rescue RestClient::Exception => e
      print_rest_exception(e, options)
      exit 1
    end
  end

  def get(args)
    options = {}
    optparse = Morpheus::Cli::OptionParser.new do |opts|
      opts.banner = subcommand_usage("[id]")
      opts.on('--refresh [SECONDS]', String, "Refresh until status is provisioned,failed. Default interval is #{default_refresh_interval} seconds.") do |val|
        options[:refresh_until_status] ||= "provisioned,failed"
        if !val.to_s.empty?
          options[:refresh_interval] = val.to_f
        end
      end
      opts.on('--refresh-until STATUS', String, "Refresh until a specified status is reached.") do |val|
        options[:refresh_until_status] = val.to_s.downcase
      end
      build_common_options(opts, options, [:json, :dry_run, :remote])
      opts.footer = "Get details about a cluster."
    end
    optparse.parse!(args)
    if args.count < 1
      puts optparse
      exit 1
    end
    connect(options)
    id_list = parse_id_list(args)
    return run_command_for_each_arg(id_list) do |arg|
      _get(arg, options)
    end
  end

  def _get(arg, options={})
    
    begin
      @clusters_interface.setopts(options)

      if options[:dry_run]
        if arg.to_s =~ /\A\d{1,}\Z/
          print_dry_run @clusters_interface.dry.get(arg.to_i)
        else
          print_dry_run @clusters_interface.dry.list({name:arg})
        end
        return 0
      end
      cluster = find_cluster_by_name_or_id(arg)
      return 1 if cluster.nil?
      json_response = nil
      if arg.to_s =~ /\A\d{1,}\Z/
        json_response = {'cluster' => cluster}  # skip redundant request
      else
        json_response = @clusters_interface.get(cluster['id'])
      end

      if options[:json]
        print JSON.pretty_generate(json_response)
        print "\n"
        return
      end

      cluster = json_response['cluster']
      worker_stats = cluster['workerStats']
      clusterType = find_cluster_type_by_id(cluster['type']['id'])

      print_h1 "Morpheus Cluster"
      print cyan
      description_cols = {
          "ID" => 'id',
          "Name" => 'name',
          "Type" => lambda { |it| it['type']['name'] },
          "Code" => 'code',
          "Group" => lambda { |it| it['site']['name'] },
          "Cloud" => lambda { |it| it['zone']['name'] },
          "Location" => lambda { |it| it['location'] },
          "Visibility" => lambda { |it| it['visibility'].to_s.capitalize },
          #"Groups" => lambda {|it| it['groups'].collect {|g| g.instance_of?(Hash) ? g['name'] : g.to_s }.join(', ') },
          #"Owner" => lambda {|it| it['owner'].instance_of?(Hash) ? it['owner']['name'] : it['ownerId'] },
          #"Tenant" => lambda {|it| it['account'].instance_of?(Hash) ? it['account']['name'] : it['accountId'] },
          "Created By" => lambda {|it| it['createdBy'] ? it['createdBy']['username'] : '' },
          "Enabled" => lambda { |it| format_boolean(it['enabled']) },
          "Status" => lambda { |it| format_cluster_status(it) }
      }
      print_description_list(description_cols, cluster)

      print_h2 "Cluster Details"
      print cyan
{'fraction_non_alphanumeric': 0.12803613744075829, 'fraction_numerical': 0.002221563981042654, 'mean_word_length': 3.1086096744752054, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 36, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7292528', 'n_tokens_mistral': 4365, 'n_tokens_neox': 4238, 'n_words': 868}