/*
 * ******************************************************
 * Copyright 2016-2020 VMware, Inc.  All Rights Reserved.
 * ******************************************************
 */

using AppUtil;
using System;
using System.Linq;
using System.Collections.Generic;
using VsanHealthApi;

namespace VsanHealthSdk
{
    class VsanApiSample
    {
        private static AppUtil.AppUtil vimConn = null;
        private static VsanhealthService vsanHealthConn = null;

        private static ManagedObjectReference vsanHealthSystem = null;
        private static ManagedObjectReference vsanPerfSystem = null;

        public VsanApiSample(string[] args)
        {
            vimConn = AppUtil.AppUtil.initialize("ClusterStatus",
                VsanHealthSdk.VsanApiSample.ConstructOptions(), args);
            Dictionary<string, ManagedObjectReference> vsanSystems = VsanApiHelper.GetVsanMos();
            vsanHealthSystem = vsanSystems[VsanApiHelper.VSAN_VC_HEALTH_SYSTEM_VALUE];
            vsanPerfSystem = vsanSystems[VsanApiHelper.VSAN_PERFORMANCE_SYSTEM_VALUE];
        }

        public String GetClusterName()
        {
            return vimConn.get_option("clusterName");
        }

        public ManagedObjectReference Connect()
        {
            vimConn.connect();
            vsanHealthConn = VsanApiHelper.ConstructVsanHealthConnection(vimConn);

            if (VsanApiHelper.IsEsx(vimConn))
            {
                return null;
            }

            ManagedObjectReference clusterMoRef = VsanApiHelper.convertMo(
                vimConn._svcUtil.getEntityByName("ClusterComputeResource", GetClusterName()));

            return clusterMoRef;
        }

        public void GetHealthVersion(ManagedObjectReference clusterMoRef)
        {
            bool fetchFromCache = true;
            bool fetchFromCacheSpecified = true;
            bool includeObjectUuid = true;
            bool includeObjectUuidSpecified = true;
            int vmCreateTimeout = 0;
            bool vmCreateTimeoutSpecified = false;
            string perspective = null;

            VsanClusterHealthSummary healthSummary =
                vsanHealthConn.VsanQueryVcClusterHealthSummary(
                        vsanHealthSystem, clusterMoRef,
                        vmCreateTimeout, vmCreateTimeoutSpecified, null,
                        includeObjectUuid, includeObjectUuidSpecified, null,
                        fetchFromCache, fetchFromCacheSpecified, perspective,
                        null, null);

            Console.WriteLine("Get vCenter health version: " +
                healthSummary.clusterVersions.vcVersion);
        }

        public void RepairClusterObjects(ManagedObjectReference clusterMoRef)
        {
            ManagedObjectReference vsanTask =
                vsanHealthConn.VsanHealthRepairClusterObjectsImmediate(
                    vsanHealthSystem, clusterMoRef, null);
            VsanApiHelper.monitorTask(vimConn, "Repair Cluster Objects", vsanTask);
        }

        public void GetVsanPerfNodeInfo(ManagedObjectReference clusterMoRef)
        {
            VsanPerfNodeInformation[] nodeInfo =
                vsanHealthConn.VsanPerfQueryNodeInformation(
                    vsanPerfSystem, clusterMoRef);

            foreach (VsanPerfNodeInformation info in nodeInfo)
            {
                Console.WriteLine("Hostname: " + "");
                Console.WriteLine("  version: " + info.version);
                Console.WriteLine("  isCmmdsMaster: " + info.isCmmdsMaster);
                Console.WriteLine("  isStatsMaster: " + info.isStatsMaster);
                Console.WriteLine("  vsanMasterUuid: " + info.vsanMasterUuid);
                Console.WriteLine("  vsanNodeUuid: " + info.vsanNodeUuid);
            }
        }

        public void Disconnect()
        {
            vimConn.disConnect();
        }

        private static OptionSpec[] ConstructOptions()
        {
            OptionSpec[] useroptions = new OptionSpec[1];
            useroptions[0] = new OptionSpec("clusterName", "String", 1,
                                            "Specifies the name of the cluster/host",
                                            null);
            return useroptions;
        }

        public static void Main(String[] args)
        {
            try
            {
                if (args[0] == "vsanhealth") {
                    args = args.Where((source, index) => index != 0).ToArray();
                    var sample = new VsanApiSample(args);
                    try
                    {
                        Console.WriteLine("Connecting to '" +
                            sample.GetClusterName() + "'...");
                        ManagedObjectReference clusterMoRef = sample.Connect();
                        if (clusterMoRef == null)
                        {
                            Console.WriteLine("Connected to Host:'" +
                                sample.GetClusterName() + "'!");
                            sample.GetVsanPerfNodeInfo(clusterMoRef);
                        }
                        else
                        {
                            Console.WriteLine("Connected to Cluster: '" +
                                sample.GetClusterName() + "'!");
                            sample.GetHealthVersion(clusterMoRef);
                            sample.RepairClusterObjects(clusterMoRef);
                        }
                    }
                    finally
                    {
                        sample.Disconnect();
                    }
                }
                else if (args[0] == "vsaniscsi")
                {
                    args = args.Where((source, index) => index != 0).ToArray();
                    var sample = new VsanIscsiSample(args);
                    try
                    {
                        Console.WriteLine("Connecting to '" +
                            sample.GetClusterName() + "'...");
                        ManagedObjectReference cluster = sample.Connect();
                        Console.WriteLine("Connected to Cluster: '" + sample.GetClusterName() + "'!");
                        sample.EnableIscsiService(cluster);
                        String targetAlias = "sampleTarget";
                        sample.CreateIscsiTargetAndLun(cluster, targetAlias);
                        sample.DeleteIscsiTargetAndLun(cluster, targetAlias);
                        sample.DisableIscsiService(cluster);
                    }
                    finally
                    {
                        sample.Disconnect();
                    }
                }
                else
                {
                    Console.WriteLine("You must choose vsanhealth/vsaniscsi first");
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
                Environment.Exit(1);
            }
            Environment.Exit(0);
        }
    }
}
