#!/usr/bin/env python
###
### Copyright 2014-2015 Boundary, Inc.
###
### Licensed 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.
###

import argparse
import errno
import errno
import json
import logging
import os
from pprint import pprint
import sys

import requests

'''
Class definition for import metric definitions
Sets creates or updates a metric from a JSON file
'''
class MetricImport():

  def __init__(self):
    self.metrics = None
    self.path = None
    self.parser = argparse.ArgumentParser(description='Import metric definitions')
    
    # Set defaults from environment variables
    self.email = os.environ['BOUNDARY_EMAIL']
    self.apikey = os.environ['BOUNDARY_API_TOKEN']
    self.apihost = os.environ['BOUNDARY_API_HOST']
    # If environment variable is not set then fallback to the default
    if self.apihost == None:
        self.apihost = 'premium-api.boundary.com'
  def getEnvironment(self):
    try:
      self.email = os.environ['BOUNDARY_EMAIL']
    except(KeyError):
      self.email = None
    try:
      self.apikey = os.environ['BOUNDARY_API_TOKEN']
    except(KeyError):
      self.apikey = None
    try:
      self.apihost = os.environ['BOUNDARY_API_HOST']
    except(KeyError):
        self.apihost = 'premium-api.boundary.com'

  def configureLogging(self):
    # Handle debug logging correctly
    if self.args.debug == True:
      level = logging.DEBUG
    else:
      level = logging.ERROR
    logging.basicConfig(level=level)

  def initialize(self):
    '''
    Initialize the instance
    '''
    self.getEnvironment()
    self.parseArgs()
    self.configureLogging()
    
    self.path = self.args.path
    
    # If the email and API key were supplied on the commandline
    # then the override those in environment variables
    if self.args.email != None:
      self.email = self.args.email
    if self.args.apikey != None:
      self.apikey = self.args.apikey
    
    # If we do not have either an e-mail or api key then we cannot proceed
    # exit indicating invalid arguments
    if self.email == None or self.apikey == None:
        self.parser.print_usage()
        sys.exit(errno.EINVAL)
      
  def parseArgs(self):
    '''
    Configure handling of command line arguments.
    '''
    self.parser.add_argument('-d','--debug',dest='debug',action='store_true',help='Enables debugging')
    self.parser.add_argument('-e','--email',dest='email',action='store',help='e-mail used to create the account')
    self.parser.add_argument('-f','--file',dest='path',action='store',required=True,help='Path to JSON file')
    self.parser.add_argument('-t','--api-key',dest='apikey',required=False,action='store',help='Boundary API Key')
    self.parser.add_argument('-v', dest='verbose', action='store_true',help='verbose mode')

    self.args = self.parser.parse_args()

    # Output the collected arguments
    logging.debug(self.args.apikey)
    logging.debug(self.args.debug)
    logging.debug(self.args.email)
    logging.debug(self.args.path)
    logging.debug(self.args.verbose)

  def load(self):
    '''
    Load the metrics file from the given path
    '''
    f = open(self.path,"r")
    self.metrics_json = f.read()

  def parse(self):
    '''
    Parse JSON into a dictionary
    '''
    self.metrics = json.loads(self.metrics_json)

  def importMetrics(self):
    '''
    1) Get command line arguments
    2) Read the JSON file
    3) Parse into a dictionary
    4) Create or update definitions using API call
    '''
    self.initialize()
    self.load()
    self.parse()
    metrics = self.metrics['result']
    for m in metrics:
      self.createUpdate(m)

  def createUpdate(self,metric):
      '''
      name - Name of the metric, must be globally unique if creating
      description - Description of the metric (optional if updating)
      displayName - Short name to use when referring to the metric (optional if updating)
      displayNameShort - Terse short name when referring to the metric and space is limited, less than 15 characters preferred. (optional if updating)
      unit - The units of measurement for the metric, can be percent, number, bytecount, or duration (optional if updating)
      defaultAggregate - When graphing (or grouping at the 1 second interval) the aggregate function that makes most sense for this metric. Can be sum, avg, max, or min. (optional if updating)
      defaultResolutionMS - Expected polling time of data in milliseconds. Used to improve rendering of graphs for non-one-second polled metrics. (optional if updating)
      isDisabled - Is this metric disabled (optional if updating)
      '''
      m = {}
      m['name'] = metric['name']
      if metric['description'] != None:
          m['description'] = metric['description']
      
      if metric['displayName'] != None:
          m['displayName'] = metric['displayName']
      
      if metric['displayNameShort'] != None:
          m['displayNameShort'] = metric['displayNameShort']
          
      if metric['unit'] != None:
          m['unit'] = metric['unit']
    
      if metric['defaultAggregate'] != None:
          m['defaultAggregate'] = metric['defaultAggregate']
          
      if metric['defaultResolutionMS'] != None:
          m['defaultResolutionMS'] = metric['defaultResolutionMS']

      if metric['isDisabled'] != None:
          m['isDisabled'] = metric['isDisabled']
          
      url = "https://{0}/v1/metrics/{1}".format(self.apihost,metric['name'])

      payload = json.dumps(m)
      headers = {'content-type': 'application/json'}
      r = requests.put(url,data=payload,headers=headers,auth=(self.email,self.apikey))
      if r.status_code != 200:
        logging.error(url)
        logging.error(headers)
        logging.error(r)
        
if __name__ == "__main__":
  p = MetricImport()
  p.importMetrics()
