import logging

from collections import namedtuple

from dtest import RUN_STATIC_UPGRADE_MATRIX
from conftest import cassandra_dir_and_version

import ccmlib.repository
from ccmlib.common import get_version_from_build

from enum import Enum

logger = logging.getLogger(__name__)

# UpgradePath's contain data about upgrade paths we wish to test
# They also contain VersionMeta's for each version the path is testing
UpgradePath = namedtuple('UpgradePath', ('name', 'starting_version', 'upgrade_version', 'starting_meta', 'upgrade_meta'))

VERSION_FAMILY = None
CONFIG = None

# TODO add a new item whenever Cassandra is branched and update TRUNK to the version present in trunk
CASSANDRA_2_0 = '2.0'
CASSANDRA_2_1 = '2.1'
CASSANDRA_2_2 = '2.2'
CASSANDRA_3_0 = '3.0'
CASSANDRA_3_11 = '3.11'
CASSANDRA_4_0 = '4.0'
TRUNK = CASSANDRA_4_0

def is_same_family_current_to_indev(origin, destination):
    """
    Within a version family it is useful to test that a prior release can upgrade to the indev version
    """
    return origin.family == destination.family and origin.variant == "current" and destination.variant == "indev"


class VersionSelectionStrategies(Enum):
    """
    Allow all versions
    """
    ALL=(lambda origin, destination: True,)
    """
    Test upgrading from indev -> indev, current -> current across versions, and current -> indev within a version
    """
    BOTH=(lambda origin, destination: (origin.variant == destination.variant) or is_same_family_current_to_indev(origin,destination),)
    """
    Exclusively test in development branches so your bug fixes show up
    """
    INDEV=(lambda origin, destination: origin.variant == 'indev' and destination.variant == 'indev' or is_same_family_current_to_indev(origin, destination),)
    """
    Test upgrading from releases to the latest release as well as from the current release to the indev tip 
    within the same version.
    """
    RELEASES=(lambda origin, destination: not VersionSelectionStrategies.INDEV.value[0](origin, destination) or is_same_family_current_to_indev(origin, destination),)


def set_config(config):
    global CONFIG
    CONFIG = config
    set_version_family()


def set_version_family():
    """
    Detects the version family (line) using dtest.py:CASSANDRA_VERSION_FROM_BUILD
    """
    # todo CASSANDRA-14421
    # current_version = CASSANDRA_VERSION_FROM_BUILD
    # There are times when we want to know the C* version we're testing against
    # before we call Tester.setUp. In the general case, we can't know that -- the
    # test method could use any version it wants for self.cluster. However, we can
    # get the version from build.xml in the C* repository specified by
    # CASSANDRA_VERSION or CASSANDRA_DIR. This should use the same resolution
    # strategy as the actual checkout code in Tester.setUp; if it does not, that is
    # a bug.
    cassandra_version_slug = CONFIG.getoption("--cassandra-version")
    cassandra_dir = CONFIG.getoption("--cassandra-dir") or CONFIG.getini("cassandra_dir")
    # Prefer CASSANDRA_VERSION if it's set in the environment. If not, use CASSANDRA_DIR
    if cassandra_version_slug:
        # fetch but don't build the specified C* version
        ccm_repo_cache_dir, _ = ccmlib.repository.setup(cassandra_version_slug)
        current_version = get_version_from_build(ccm_repo_cache_dir)
    else:
        current_version = get_version_from_build(cassandra_dir)

    # TODO add a new item whenever Cassandra is branched
    if current_version.vstring.startswith('2.0'):
        version_family = CASSANDRA_2_0
    elif current_version.vstring.startswith('2.1'):
        version_family = CASSANDRA_2_1
    elif current_version.vstring.startswith('2.2'):
        version_family = CASSANDRA_2_2
    elif current_version.vstring.startswith('3.0'):
        version_family = CASSANDRA_3_0
    elif current_version.vstring.startswith('3.11'):
        version_family = CASSANDRA_3_11
    elif current_version.vstring.startswith('4.0'):
        version_family = CASSANDRA_4_0
    else:
        # when this occurs, it's time to update this manifest a bit!
        raise RuntimeError("Testing upgrades from/to version %s is not supported. Please use a custom manifest (see upgrade_manifest.py)" % current_version.vstring)

    global VERSION_FAMILY
    VERSION_FAMILY = version_family
    logger.info("Setting version family to %s\n" % VERSION_FAMILY)


class VersionMeta(namedtuple('_VersionMeta', ('name', 'family', 'variant', 'version', 'min_proto_v', 'max_proto_v', 'java_versions'))):
    """
    VersionMeta's are namedtuples that capture data about version family, protocols supported, and current version identifiers
    they must have a 'variant' value of 'current' or 'indev', where 'current' means most recent released version,
    'indev' means where changing code is found.
    """
    @property
    def java_version(self):
        return max(self.java_versions)

    @property
    def matches_current_env_version_family(self):
        """
        Returns boolean indicating whether this meta matches the current version family of the environment.

        e.g. Returns true if the current env version family is 3.x and the meta's family attribute is a match.
        """
        return self.family == VERSION_FAMILY

    @property
    def matches_current_env_version_family_and_is_indev(self):
        """
        Returns boolean indicating whether this meta matches the current version family of the environment
        and whether this meta is in indev variant
        """
        return self.family == VERSION_FAMILY and self.variant == "indev"

    def clone_with_local_env_version(self):
        """
        Returns a new object cloned from this one, with the version replaced with the local env version.
        """
        cassandra_dir, cassandra_version = cassandra_dir_and_version(CONFIG)
        if cassandra_version:
            return self._replace(version=cassandra_version)
        return self._replace(version="clone:{}".format(cassandra_dir))


# TODO define new versions whenever Cassandra is branched
indev_2_1_x = VersionMeta(name='indev_2_1_x', family=CASSANDRA_2_1, variant='indev', version='github:apache/cassandra-2.1', min_proto_v=1, max_proto_v=3, java_versions=(7, 8))
current_2_1_x = VersionMeta(name='current_2_1_x', family=CASSANDRA_2_1, variant='current', version='2.1.22', min_proto_v=1, max_proto_v=3, java_versions=(7, 8))

indev_2_2_x = VersionMeta(name='indev_2_2_x', family=CASSANDRA_2_2, variant='indev', version='github:apache/cassandra-2.2', min_proto_v=1, max_proto_v=3, java_versions=(7, 8))
current_2_2_x = VersionMeta(name='current_2_2_x', family=CASSANDRA_2_2, variant='current', version='2.2.19', min_proto_v=1, max_proto_v=3, java_versions=(7, 8))

indev_3_0_x = VersionMeta(name='indev_3_0_x', family=CASSANDRA_3_0, variant='indev', version='github:apache/cassandra-3.0', min_proto_v=3, max_proto_v=4, java_versions=(8,))
current_3_0_x = VersionMeta(name='current_3_0_x', family=CASSANDRA_3_0, variant='current', version='3.0.24', min_proto_v=3, max_proto_v=4, java_versions=(8,))

indev_3_11_x = VersionMeta(name='indev_3_11_x', family=CASSANDRA_3_11, variant='indev', version='github:apache/cassandra-3.11', min_proto_v=3, max_proto_v=4, java_versions=(8,))
current_3_11_x = VersionMeta(name='current_3_11_x', family=CASSANDRA_3_11, variant='current', version='3.11.9', min_proto_v=3, max_proto_v=4, java_versions=(8,))

indev_trunk = VersionMeta(name='indev_trunk', family=TRUNK, variant='indev', version='github:apache/trunk', min_proto_v=4, max_proto_v=5, java_versions=(8,))


# MANIFEST maps a VersionMeta representing a line/variant to a list of other VersionMeta's representing supported upgrades
# Note on versions: 2.0 must upgrade to 2.1. Once at 2.1 or newer, upgrade is supported to any later version, including trunk (for now).
# "supported upgrade" means a few basic things, for an upgrade of version 'A' to higher version 'B':
#   1) The cluster will function in a mixed-version state, with some nodes on version A and some nodes on version B. Schema modifications are not supported on mixed-version clusters.
#   2) Features exclusive to version B may not work until all nodes are running version B.
#   3) Nodes upgraded to version B can read data stored by the predecessor version A, and from a data standpoint will function the same as if they always ran version B.
#   4) If a new sstable format is present in version B, writes will occur in that format after upgrade. Running sstableupgrade on version B will proactively convert version A sstables to version B.
# TODO define new upgrade scenarios whenever Cassandra is branched
MANIFEST = {
    current_2_1_x: [indev_2_2_x, indev_3_0_x, indev_3_11_x],
    current_2_2_x: [indev_2_2_x, indev_3_0_x, indev_3_11_x],
    current_3_0_x: [indev_3_0_x, indev_3_11_x, indev_trunk],
    current_3_11_x: [indev_3_11_x, indev_trunk],

    indev_2_2_x: [indev_3_0_x, indev_3_11_x],
    indev_3_0_x: [indev_3_11_x, indev_trunk],
    indev_3_11_x: [indev_trunk]
}

def _have_common_proto(origin_meta, destination_meta):
    """
    Takes two VersionMeta objects, in order of test from start version to next version.
    Returns a boolean indicating if the given VersionMetas have a common protocol version.
    """
    return origin_meta.max_proto_v >= destination_meta.min_proto_v

def build_upgrade_pairs():
    """
    Using the manifest (above), builds a set of valid upgrades, according to current testing practices.

    Returns a list of UpgradePath's.
    """
    valid_upgrade_pairs = []
    manifest = MANIFEST

    configured_strategy = CONFIG.getoption("--upgrade-version-selection").upper()
    version_select_strategy = VersionSelectionStrategies[configured_strategy].value[0]
    filter_for_current_family = CONFIG.getoption("--upgrade-target-version-only")

    for origin_meta, destination_metas in list(manifest.items()):
        for destination_meta in destination_metas:
            if not version_select_strategy(origin_meta, destination_meta):
                continue

            if not (origin_meta and destination_meta):  # None means we don't care about that version, which means we don't care about iterations involving it either
                logger.debug("skipping class creation as a version is undefined (this is normal), versions: {} and {}".format(origin_meta, destination_meta))
                continue

            if not _have_common_proto(origin_meta, destination_meta):
                logger.debug("skipping class creation, no compatible protocol version between {} and {}".format(origin_meta.name, destination_meta.name))
                continue

            # if either origin or destination match version, then do the test
            # the assumption is that a change in 3.0 could break upgrades to trunk, so include those tests as well
            if filter_for_current_family and not origin_meta.matches_current_env_version_family_and_is_indev and not destination_meta.matches_current_env_version_family:
                logger.debug("skipping class creation, origin version {} and destination version {} do not match target version {}, and --upgrade-target-version-only was set".format(origin_meta.name, destination_meta.name, VERSION_FAMILY))
                continue

            path_name = 'Upgrade_' + origin_meta.name + '_To_' + destination_meta.name

            if not RUN_STATIC_UPGRADE_MATRIX:
                if destination_meta.matches_current_env_version_family:
                    # looks like this test should actually run in the current env, so let's set the final version to match the env exactly
                    oldmeta = destination_meta
                    newmeta = destination_meta.clone_with_local_env_version()
                    logger.debug("{} appears applicable to current env. Overriding final test version from {} to {}".format(path_name, oldmeta.version, newmeta.version))
                    destination_meta = newmeta

            valid_upgrade_pairs.append(
                UpgradePath(
                    name=path_name,
                    starting_version=origin_meta.version,
                    upgrade_version=destination_meta.version,
                    starting_meta=origin_meta,
                    upgrade_meta=destination_meta
                )
            )

    return valid_upgrade_pairs
