# Wizard Kit: Functions - PNG graph for I/O Benchmark

import base64
import Gnuplot
import json
import math
import requests

from functions.common import *


# Functions
def export_io_graph(disk):
  """Exports PNG graph using gnuplot, returns file path as str."""
  read_rates = disk.tests['I/O Benchmark'].read_rates
  if not read_rates:
    # No data, aborting
    raise GenericError
  max_rate = max(read_rates) / (1024**2)
  max_rate = max(800, max_rate)
  out_path = '{}/iobenchmark-{}.png'.format(
    global_vars['LogDir'], disk.name)
  plot_data = '{}/iobenchmark-{}-plot.data'.format(
    global_vars['LogDir'], disk.name)

  # Adjust Y-axis range to either 1000 or roughly max rate + 200
  ## Round up to the nearest 100 and then add 200
  y_range = (math.ceil(max_rate/100)*100) + 200

  # Save plot data to file for Gnuplot
  with open(plot_data, 'w') as f:
    for i in range(len(read_rates)):
      _percent = ( (i+1) / len(read_rates) ) * 100
      _rate = int( read_rates[i] / (1024**2) )
      f.write('{:0.1f} {}\n'.format(_percent, _rate))

  # Run gnuplot commands
  g = Gnuplot.Gnuplot()
  g('reset')
  g('set output "{}"'.format(out_path))
  g('set terminal png large size 660,300 truecolor font "Noto Sans,11"')
  g('set title "I/O Benchmark"')
  g('set yrange [0:{}]'.format(y_range))
  g('set style data lines')
  g('plot "{}" title "{}"'.format(
    plot_data,
    disk.description.replace('_', ' '),
    ))

  # Cleanup
  g.close()
  del(g)

  return out_path


def upload_to_imgur(image_path):
  """Upload image to Imgur and return image url as str."""
  image_data = None
  image_link = None

  # Bail early
  if not image_path:
    raise GenericError

  # Read image file and convert to base64 then convert to str
  with open(image_path, 'rb') as f:
    image_data = base64.b64encode(f.read()).decode()

  # POST image
  url = "https://api.imgur.com/3/image"
  boundary = '----WebKitFormBoundary7MA4YWxkTrZu0gW'
  payload = ('--{boundary}\r\nContent-Disposition: form-data; '
             'name="image"\r\n\r\n{data}\r\n--{boundary}--')
  payload = payload.format(boundary=boundary, data=image_data)
  headers = {
    'content-type': 'multipart/form-data; boundary={}'.format(boundary),
    'Authorization': 'Client-ID {}'.format(IMGUR_CLIENT_ID),
    }
  response = requests.request("POST", url, data=payload, headers=headers)

  # Return image link
  if response.ok:
    json_data = json.loads(response.text)
    image_link = json_data['data']['link']
  return image_link


def upload_to_nextcloud(image_path, ticket_number, dev_name):
  """Upload image to Nextcloud server and return folder url as str."""
  image_data = None

  # Bail early
  if not image_path:
    raise GenericError

  # Read image file and convert to base64
  with open(image_path, 'rb') as f:
    image_data = f.read()

  # PUT image
  url = '{base_url}/{ticket_number}_iobenchmark_{dev_name}_{date}.png'.format(
    base_url=BENCHMARK_SERVER['Url'],
    ticket_number=ticket_number,
    dev_name=dev_name,
    date=global_vars.get('Date-Time', 'Unknown Date-Time'))
  requests.put(
    url,
    data=image_data,
    headers = {'X-Requested-With': 'XMLHttpRequest'},
    auth = (BENCHMARK_SERVER['User'], BENCHMARK_SERVER['Pass']))

  # Return folder link
  return BENCHMARK_SERVER['Short Url']


if __name__ == '__main__':
  print("This file is not meant to be called directly.")

# vim: sts=2 sw=2 ts=2
