const fs = require('fs');

const axios = require('axios');
const { stringify } = require('javascript-stringify');

class QuickChart {
  constructor(apiKey, accountId) {
    this.apiKey = apiKey;
    this.accountId = accountId;

    this.host = 'quickchart.io';
    this.protocol = 'https';
    this.baseUrl = `${this.protocol}://${this.host}`;

    this.chart = undefined;
    this.width = 500;
    this.height = 300;
    this.devicePixelRatio = 1.0;
    this.backgroundColor = '#ffffff';
    this.format = 'png';
  }

  setConfig(chartConfig) {
    this.chart = stringify(chartConfig);
    return this;
  }

  setWidth(width) {
    this.width = parseInt(width, 10);
    return this;
  }

  setHeight(height) {
    this.height = parseInt(height, 10);
    return this;
  }

  setBackgroundColor(color) {
    this.backgroundColor = color;
    return this;
  }

  setDevicePixelRatio(ratio) {
    this.devicePixelRatio = parseFloat(ratio);
    return this;
  }

  setFormat(fmt) {
    this.format = fmt;
    return this;
  }

  isValid() {
    if (!this.chart) {
      return false;
    }
    return true;
  }

  getUrl() {
    if (!this.isValid()) {
      throw new Error('You must call setConfig before getUrl');
    }
    const ret = new URL(`${this.baseUrl}/chart`);
    ret.searchParams.append('c', this.chart);
    ret.searchParams.append('w', this.width);
    ret.searchParams.append('h', this.height);
    if (this.devicePixelRatio !== 1.0) {
      ret.searchParams.append('devicePixelRatio', this.devicePixelRatio);
    }
    if (this.backgroundColor !== 1.0) {
      ret.searchParams.append('bkg', this.backgroundColor);
    }
    if (this.format !== 1.0) {
      ret.searchParams.append('f', this.format);
    }
    return ret.href;
  }

  getPostData() {
    const { width, height, chart, format, backgroundColor, devicePixelRatio } = this;
    const postData = {
      width,
      height,
      chart,
    };
    if (format) {
      postData.format = format;
    }
    if (backgroundColor) {
      postData.backgroundColor = backgroundColor;
    }
    if (devicePixelRatio) {
      postData.devicePixelRatio = devicePixelRatio;
    }
    return postData;
  }

  async getShortUrl() {
    if (!this.isValid()) {
      throw new Error('You must call setConfig before getUrl');
    }

    const resp = await axios.post('https://quickchart.io/chart/create', this.getPostData());
    if (resp.status !== 200) {
      throw `Bad response code ${resp.status} from chart shorturl endpoint`;
    } else if (!resp.data.success) {
      throw 'Received failure response from chart shorturl endpoint';
    } else {
      return resp.data.url;
    }
  }

  async toBinary() {
    if (!this.isValid()) {
      throw new Error('You must call setConfig before getUrl');
    }

    const resp = await axios.post('https://quickchart.io/chart', this.getPostData(), {
      responseType: 'arraybuffer',
    });
    if (resp.status !== 200) {
      throw `Bad response code ${resp.status} from chart shorturl endpoint`;
    }
    return Buffer.from(resp.data, 'binary');
  }

  async toDataUrl() {
    const buf = await this.toBinary();
    const b64buf = buf.toString('base64');
    return `data:image/png;base64,${b64buf}`;
  }

  async toFile(pathOrDescriptor) {
    const buf = await this.toBinary();
    fs.writeFileSync(pathOrDescriptor, buf);
  }
}

module.exports = QuickChart;