from .Server import Server
from json import dumps, loads
from pprint import pprint
from datetime import datetime
from os import mkdir
from os.path import isdir

class Environment:
# Environment
#
# Represents a configuration environment which may contain
# one or more servers. It is created by the dbtool CLI and
# can be saved and restored from .dbconfig files.
#

  def __init__(self, from_plain=None, **kwargs):
  # Constructor
  #
  # Properties
  #   __class: string with object class
  #   name: string with environment name
  #   servers: list of Server objects
  #   filepath: relative path to .dbconfig file associated to environment
  #

    if from_plain:
      self.__class = 'Environment',
      self.name = from_plain.get('name', '')
      self.servers = list(map(
        lambda server: Server(from_plain=server)
      , from_plain.get('servers', [])))
      self.filepath = from_plain.get('filepath', '')
      self.targets = loads(from_plain.get('targets', {}))
    else:
      self.__class = 'Environment'
      self.name = kwargs.get('name', '')
      self.__servers = []
      self.servers = kwargs.get('servers', [])
      self.filepath = kwargs.get('filepath', '')
      self.targets = kwargs.get('targets', {})

  def __repr__(self):

    return (
      'Environment object \'{name}\' containing {s_count} server(s)'.format(name=self.name, s_count=len(self.servers))
    )

  def analyze(self):
  # analyze
  #
  # Calls analysis functions in a nest recursion fashion
  # towards specified targets passing to them the write
  # function. As the target argument gets passed down, it
  # gets mutated so that calls to analyze with very specific
  # targets always provide the required context and data for
  # accessing the servers to the relevant objects.
  #

    # Initialize logs
    #
    log_path = 'logs/{name}-{timestamp}'.format(name=self.name, timestamp=datetime.now().isoformat())
    if not isdir('logs'):
      mkdir('logs')
    mkdir(log_path)

    # Call analyze in servers
    #
    target_servers = list(filter(
      lambda server: server.name in self.targets.keys()
    , self.servers))
    server_returns = list(map(
      lambda server: server.analyze(self.targets[server.name], log_path)
    , target_servers))

    # Count issues
    #
    issues_servers = 0
    try:
      issues_servers += len(server_returns)
    except:
      pass
    issues_databases = 0
    try:
      issues_databases += sum(list(map( lambda server: server['collections'], server_returns )))
    except:
      pass
    issues_collections = 0
    try:
      issues_collections += sum(list(map( lambda server: server['databases'], server_returns )))
    except:
      pass
    issues_documents = 0
    try:
      issues_documents += sum(list(map( lambda server: server['documents'], server_returns )))
    except:
      pass
    issues_properties = 0
    try:
      issues_properties += sum(list(map( lambda server: server['properties'], server_returns )))
    except:
      pass

    # Create environment summary
    #
    with open(log_path+'/{environment}.log'.format(environment=self.name), 'w') as log_file:
      log_file.write(dumps({
        'environment': self.name,
        'servers': list(map(
          lambda server: server.name
        , self.servers)),
        'analysisTargets': list(self.targets.keys()),
        'issues': {
          'servers': issues_servers,
          'databases': issues_databases,
          'collections': issues_collections,
          'documents': issues_documents,
          'properties': issues_properties
        }
      }))

    return {
      'path': log_path,
      'issues': {
        'servers': issues_servers,
        'databases': issues_databases,
        'collections': issues_collections,
        'documents': issues_documents,
        'properties': issues_properties
      }
    }
  
  def to_plain(self):
  # to_plain
  #
  # Returns a plain python object representing the Environment object
  #

    plain_servers = list(map(
      lambda server: server.to_plain()
    , self.servers))
    
    return {
      '__class': self.__class,
      'name': self.name,
      'filepath': self.filepath,
      'servers': plain_servers,
      'targets': dumps(self.targets)
    }
  
  @property
  def name(self):
    return self.__name
  @name.setter
  def name(self, new_name):
    if isinstance(new_name, str):
      self.__name = new_name

  @property
  def servers(self):
    return self.__servers
  @servers.setter
  def servers(self, new_servers):
    if isinstance(new_servers, list):
      self.__servers = new_servers
  
  def add_servers(self, new_servers):
    if isinstance(new_servers, list):
      self.__servers.extend(new_servers)
  
  def has_server(self, b):
    for server in self.servers:
      if server == b:
        return True
    return False
  
  @property
  def filepath(self):
    return self.__filepath
  @filepath.setter
  def filepath(self, new_filepath):
    if isinstance(new_filepath, str):
      self.__filepath = new_filepath
  
  @property
  def targets(self):
    return self.__targets
  @targets.setter
  def targets(self, new_targets):
    if isinstance(new_targets, dict):
      self.__targets = new_targets
from .Server import Server
from json import dumps, loads
from pprint import pprint
from datetime import datetime
from os import mkdir
from os.path import isdir

class Environment:
# Environment
#
# Represents a configuration environment which may contain
# one or more servers. It is created by the dbtool CLI and
# can be saved and restored from .dbconfig files.
#

  def __init__(self, from_plain=None, **kwargs):
  # Constructor
  #
  # Properties
  #   __class: string with object class
  #   name: string with environment name
  #   servers: list of Server objects
  #   filepath: relative path to .dbconfig file associated to environment
  #

    if from_plain:
      self.__class = 'Environment',
      self.name = from_plain.get('name', '')
      self.servers = list(map(
        lambda server: Server(from_plain=server)
      , from_plain.get('servers', [])))
      self.filepath = from_plain.get('filepath', '')
      self.targets = loads(from_plain.get('targets', {}))
    else:
      self.__class = 'Environment'
      self.name = kwargs.get('name', '')
      self.__servers = []
      self.servers = kwargs.get('servers', [])
      self.filepath = kwargs.get('filepath', '')
      self.targets = kwargs.get('targets', {})

  def __repr__(self):

    return (
      'Environment object \'{name}\' containing {s_count} server(s)'.format(name=self.name, s_count=len(self.servers))
    )

  def analyze(self):
  # analyze
  #
  # Calls analysis functions in a nest recursion fashion
  # towards specified targets passing to them the write
  # function. As the target argument gets passed down, it
  # gets mutated so that calls to analyze with very specific
  # targets always provide the required context and data for
  # accessing the servers to the relevant objects.
  #

    # Initialize logs
    #
    log_path = 'logs/{name}-{timestamp}'.format(name=self.name, timestamp=datetime.now().isoformat())
    if not isdir('logs'):
      mkdir('logs')
    mkdir(log_path)

    # Call analyze in servers
    #
    target_servers = list(filter(
      lambda server: server.name in self.targets.keys()
    , self.servers))
    server_returns = list(map(
      lambda server: server.analyze(self.targets[server.name], log_path)
    , target_servers))

    # Count issues
    #
    issues_servers = 0
    try:
      issues_servers += len(server_returns)
    except:
      pass
    issues_databases = 0
    try:
      issues_databases += sum(list(map( lambda server: server['collections'], server_returns )))
    except:
      pass
    issues_collections = 0
    try:
      issues_collections += sum(list(map( lambda server: server['databases'], server_returns )))
    except:
      pass
    issues_documents = 0
    try:
      issues_documents += sum(list(map( lambda server: server['documents'], server_returns )))
    except:
      pass
    issues_properties = 0
    try:
      issues_properties += sum(list(map( lambda server: server['properties'], server_returns )))
    except:
      pass

    # Create environment summary
    #
    with open(log_path+'/{environment}.log'.format(environment=self.name), 'w') as log_file:
      log_file.write(dumps({
        'environment': self.name,
        'servers': list(map(
          lambda server: server.name
        , self.servers)),
        'analysisTargets': list(self.targets.keys()),
        'issues': {
          'servers': issues_servers,
          'databases': issues_databases,
          'collections': issues_collections,
          'documents': issues_documents,
          'properties': issues_properties
        }
      }))

    return {
      'path': log_path,
      'issues': {
        'servers': issues_servers,
        'databases': issues_databases,
        'collections': issues_collections,
        'documents': issues_documents,
        'properties': issues_properties
      }
    }
  
  def to_plain(self):
  # to_plain
  #
  # Returns a plain python object representing the Environment object
  #

    plain_servers = list(map(
      lambda server: server.to_plain()
    , self.servers))
    
    return {
      '__class': self.__class,
      'name': self.name,
      'filepath': self.filepath,
      'servers': plain_servers,
      'targets': dumps(self.targets)
    }
  
  @property
  def name(self):
    return self.__name
  @name.setter
  def name(self, new_name):
    if isinstance(new_name, str):
      self.__name = new_name

  @property
  def servers(self):
    return self.__servers
  @servers.setter
  def servers(self, new_servers):
    if isinstance(new_servers, list):
      self.__servers = new_servers
  
  def add_servers(self, new_servers):
    if isinstance(new_servers, list):
      self.__servers.extend(new_servers)
  
  def has_server(self, b):
    for server in self.servers:
      if server == b:
        return True
    return False
  
  @property
  def filepath(self):
    return self.__filepath
  @filepath.setter
  def filepath(self, new_filepath):
    if isinstance(new_filepath, str):
      self.__filepath = new_filepath
  
  @property
  def targets(self):
    return self.__targets
  @targets.setter
  def targets(self, new_targets):
    if isinstance(new_targets, dict):
      self.__targets = new_targets
# Environment # # Represents a configuration environment which may contain # one or more servers. It is created by the dbtool CLI and # can be saved and restored from .dbconfig files. # # Constructor # # Properties #   __class: string with object class #   name: string with environment name #   servers: list of Server objects #   filepath: relative path to .dbconfig file associated to environment # # analyze # # Calls analysis functions in a nest recursion fashion # towards specified targets passing to them the write # function. As the target argument gets passed down, it # gets mutated so that calls to analyze with very specific # targets always provide the required context and data for # accessing the servers to the relevant objects. # # Initialize logs # # Call analyze in servers # # Count issues # # Create environment summary # # to_plain # # Returns a plain python object representing the Environment object #