#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements.  See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License.  You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

"""
Utility methods
"""

import os
import sys
from os.path import isfile, join
from optparse import OptionParser


class EC2Type:
    def __init__(self, arch, ephemeral=1, has_nvme=False):
        self.arch = arch
        self.ephemeral = ephemeral
        self.has_nvme = has_nvme


AMI_HELP_MSG = """PLEASE NOTE - If you have accepted the software terms for the selected AMI and still get an error,
this could be due to the publisher releasing new images of that OS. When this occurs, the old images
are no longer available to new users. You will then need to visit the publisher's page and find the latest AMI ID
for your EC2 region. This should be used to set the 'aws_ami' property in your muchos.props.
After setting the 'aws_ami' property, run the launch command again.

The Fedora Project also makes available AMIs for their Fedora Cloud releases. The list of Fedora Cloud AMIs
can be viewed at https://fedoraproject.org/cloud/download and clicking on the AWS link."
"""  # noqa

instance_types = {
    "c1.medium": EC2Type("pvm"),
    "c1.xlarge": EC2Type("pvm", 4),
    "c3.2xlarge": EC2Type("pvm", 2),
    "c3.4xlarge": EC2Type("pvm", 2),
    "c3.8xlarge": EC2Type("pvm", 2),
    "c3.large": EC2Type("pvm", 2),
    "c3.xlarge": EC2Type("pvm", 2),
    "cc2.8xlarge": EC2Type("hvm", 4),
    "cg1.4xlarge": EC2Type("hvm", 2),
    "cr1.8xlarge": EC2Type("hvm", 2),
    "hi1.4xlarge": EC2Type("pvm", 2),
    "hs1.8xlarge": EC2Type("pvm", 24),
    "i2.2xlarge": EC2Type("hvm", 2),
    "i2.4xlarge": EC2Type("hvm", 4),
    "i2.8xlarge": EC2Type("hvm", 8),
    "i2.xlarge": EC2Type("hvm"),
    "i3.large": EC2Type("hvm", 1, True),
    "i3.xlarge": EC2Type("hvm", 1, True),
    "i3.2xlarge": EC2Type("hvm", 1, True),
    "i3.4xlarge": EC2Type("hvm", 2, True),
    "m1.large": EC2Type("pvm", 2),
    "m1.medium": EC2Type("pvm"),
    "m1.small": EC2Type("pvm"),
    "m1.xlarge": EC2Type("pvm", 4),
    "m2.2xlarge": EC2Type("pvm", 1),
    "m2.4xlarge": EC2Type("pvm", 2),
    "m2.xlarge": EC2Type("pvm"),
    "m3.2xlarge": EC2Type("hvm", 2),
    "m3.large": EC2Type("hvm"),
    "m3.medium": EC2Type("hvm"),
    "m3.xlarge": EC2Type("hvm", 2),
    "m5d.large": EC2Type("hvm", 1, True),
    "m5d.xlarge": EC2Type("hvm", 1, True),
    "m5d.2xlarge": EC2Type("hvm", 1, True),
    "m5d.4xlarge": EC2Type("hvm", 2, True),
    "m5d.12xlarge": EC2Type("hvm", 2, True),
    "m5d.24xlarge": EC2Type("hvm", 4, True),
    "r3.2xlarge": EC2Type("hvm", 1),
    "r3.4xlarge": EC2Type("hvm", 1),
    "r3.8xlarge": EC2Type("hvm", 2),
    "r3.large": EC2Type("hvm", 1),
    "r3.xlarge": EC2Type("hvm", 1),
    "d2.xlarge": EC2Type("hvm", 3),
    "d2.2xlarge": EC2Type("hvm", 6),
    "d2.4xlarge": EC2Type("hvm", 12),
    "d2.8xlarge": EC2Type("hvm", 24),
}


def verify_type(instance_type):
    if instance_type not in instance_types:
        print(
            "ERROR - EC2 instance type '{}' is currently "
            "not supported!".format(instance_type)
        )
        print("This is probably due to the instance type being EBS-only.")
        print("Below is a list of supported instance types:")
        for key in instance_types:
            print(key)
        sys.exit(1)


def get_arch(instance_type):
    verify_type(instance_type)
    return instance_types.get(instance_type).arch


def get_ephemeral_devices(instance_type):
    verify_type(instance_type)
    devices = []
    ec2_type = instance_types.get(instance_type)

    start = 0
    if instance_type.startswith("m5d"):
        start = 1

    for i in range(start, ec2_type.ephemeral + start):
        if ec2_type.has_nvme:
            devices.append("/dev/nvme" + str(i) + "n1")
        else:
            devices.append("/dev/xvd" + chr(ord("b") + i))

    return devices


def get_block_device_map(instance_type):
    verify_type(instance_type)

    bdm = [{"DeviceName": "/dev/sda1", "Ebs": {"DeleteOnTermination": True}}]

    ec2_type = instance_types.get(instance_type)
    if not ec2_type.has_nvme:
        for i in range(0, ec2_type.ephemeral):
            device = {
                "DeviceName": "/dev/xvd" + chr(ord("b") + i),
                "VirtualName": "ephemeral" + str(i),
            }
            bdm.append(device)

    return bdm


def parse_args(hosts_dir, input_args=None):
    parser = OptionParser(
        usage="muchos [options] <action>\n\n"
        + "where <action> can be:\n"
        + "  launch           Launch cluster in Azure or EC2\n"
        + "  status           Check status of Azure or EC2 cluster\n"
        + "  setup            Set up cluster\n"
        + "  sync             Sync ansible directory on cluster proxy node\n"
        + "  config           Print configuration for that cluster. "
        "Requires '-p'. Use '-p all' for all config.\n"
        + "  stop             Stops instance\n"
        + "  start            Starts instance\n"
        + "  ssh              SSH to cluster proxy node\n"
        + "  kill             Kills processes on cluster started by Muchos\n"
        + "  wipe             Wipes cluster data and kills processes\n"
        + "  terminate        Terminate EC2 cluster\n"
        + "  cancel_shutdown  Cancels automatic shutdown of EC2 cluster",
        add_help_option=False,
    )
    parser.add_option(
        "-c", "--cluster", dest="cluster", help="Specifies cluster"
    )
    parser.add_option(
        "-p",
        "--property",
        dest="property",
        help="Specifies property to print (if using 'config' action)"
        ". Set to 'all' to print every property",
    )
    parser.add_option(
        "-h", "--help", action="help", help="Show this help message and exit"
    )

    if input_args:
        (opts, args) = parser.parse_args(input_args)
    else:
        (opts, args) = parser.parse_args()

    if len(args) == 0:
        print("ERROR - You must specify on action")
        return
    action = args[0]

    if action == "launch" and not opts.cluster:
        print("ERROR - You must specify a cluster if using launch command")
        return

    clusters = [f for f in os.listdir(hosts_dir) if isfile(join(hosts_dir, f))]

    if not opts.cluster:
        if len(clusters) == 0:
            print(
                "ERROR - No clusters found in conf/hosts "
                "or specified by --cluster option"
            )
            return
        elif len(clusters) == 1:
            opts.cluster = clusters[0]
        else:
            print(
                "ERROR - Multiple clusters {0} found in conf/hosts/. "
                "Please pick one using --cluster option".format(clusters)
            )
            return

    if action == "config" and not opts.property:
        print(
            "ERROR - For config action, you must set -p to a property or 'all'"
        )
        return

    return opts, action, args[1:]
