/*
A widget that displays your current Twitter follower count and growth chart, powered by your ilo.so dashboard.

(Only works for ilo.so users!)

You will need to put in your Twitter username and API key in the widget's Parameter field. 
Like this: "username:myapikey"
You can get your API key from ilo.so/settings/)

Sign up to ilo at https://ilo.so

Version 1.0.0 (March 3, 2021)
by Dan Rowden (@dr)
*/


// Chart config

const daysInChart = 7 // How many days you want to show in the chart


// Some colours you can change

const chartColor = "#c88e69"
const chartOpacity = 0.3
const widgetBgColor = "#fff7f2"
const usernameColor = '#6d6d6d'
const followersColor = '#1e272e'
const dailyChangeColor = '#b77a54'


// =====================================================================
// Here starts all the widget code. Feel free to edit below if you want!
// Share your widget on Twitter! I'm @dr :)
// =====================================================================


let twitterParameter = args.widgetParameter.split(':')
let twitterUsername = twitterParameter[0]
let apiKey = twitterParameter[1]

let url = "https://api.ilo.so/v1/stats/"+twitterUsername+"/?history="+daysInChart+'&api_key='+apiKey
let req = new Request(url)
const json = await req.loadJSON()
const followers_total = parseInt(json['followers']).toLocaleString()
const followers_today = parseInt(getCountsFromData(json['followers_daily']).pop()).toLocaleString()
const chartData = json['followers_total_daily']


// LineChart by https://kevinkub.de/
// Used as the widget background
class LineChart {
  constructor(width, height, values) {
    this.ctx = new DrawContext();
    this.ctx.size = new Size(width, height);
    this.values = getCountsFromData(values);
  }
  
  _calculatePath() {
    let maxValue = Math.max(...this.values);
    let minValue = Math.min(...this.values);
    let difference = maxValue - minValue;
    let count = this.values.length;
    let step = this.ctx.size.width / (count - 1);
    let points = this.values.map((current, index, all) => {
        let x = step*index;
        let y = this.ctx.size.height - (current - minValue) / difference * (this.ctx.size.height * 0.5);
        return new Point(x, y);
    });
    return this._getSmoothPath(points);
  }
      
  _getSmoothPath(points) {
    let path = new Path();
    path.move(new Point(0, this.ctx.size.height));
    path.addLine(points[0]);
    for(let i = 0; i < points.length-1; i++) {
      let xAvg = (points[i].x + points[i+1].x) / 2;
      let yAvg = (points[i].y + points[i+1].y) / 2;
      let avg = new Point(xAvg, yAvg);
      let cp1 = new Point((xAvg + points[i].x) / 2, points[i].y);
      let next = new Point(points[i+1].x, points[i+1].y);
      let cp2 = new Point((xAvg + points[i+1].x) / 2, points[i+1].y);
      path.addQuadCurve(avg, cp1);
      path.addQuadCurve(next, cp2);
    }
    path.addLine(new Point(this.ctx.size.width, this.ctx.size.height));
    path.closeSubpath();
    return path;
  }
  
  configure(fn) {
    let path = this._calculatePath();
    if(fn) {
      fn(this.ctx, path);
    } else {
      this.ctx.addPath(path);
      this.ctx.fillPath(path);
    }
    return this.ctx;
  }

}


// Convert API data into a simple list
function getCountsFromData(values) {
  let chartValues = []
  for(let data in values) {
    let thisDay = values[data]
    let keys = Object.keys(thisDay);
       for (let i = 0; i < keys.length; i++) {
        let val = thisDay[keys[i]];
        chartValues.push(val);
      }
  }
  return chartValues;  
}


// Fonts
const smallText = new Font("HelveticaNeue", 14);
const largeText = new Font("HelveticaNeue-Medium", 16);


// Create the widget
let w = new ListWidget()
w.backgroundColor = new Color(widgetBgColor);
w.url = 'https://ilo.so/'+twitterUsername+'/'

var refreshDate = Date.now() + 1000*60*5 // Refresh after at least 5 minutes
w.refreshAfterDate = new Date(refreshDate)


// ilo icon
let icon = await loadImage('https://ilo.so/static/favicon.png')
let iconImg = w.addImage(icon)
iconImg.imageSize = new Size(20,20)

w.addSpacer(20)


// Show username
const usernameStr = '@' + twitterUsername
textUsername = w.addText(usernameStr)
textUsername.textColor = new Color(usernameColor);
textUsername.font = smallText;

w.addSpacer(4)


// Show current follower count
const followerStr = followers_total + " followers"
textFollowers = w.addText(followerStr)
textFollowers.textColor = new Color(followersColor);
textFollowers.font = largeText

w.addSpacer(4)


// Show today's follower change
const followerTodayStr = (followers_today > -1 ? '+' : '') + followers_today + " today"
textChange = w.addText(followerTodayStr)
textChange.textColor = new Color(dailyChangeColor);
textChange.font = smallText;


// Line chart as bg
// This will create a square chart
let chart = new LineChart(1200, 1200, chartData).configure((ctx, path) => {
  ctx.opaque = false;
  ctx.setFillColor(new Color(chartColor, chartOpacity));
  ctx.addPath(path);
  ctx.fillPath(path);
}).getImage();
w.backgroundImage = chart



// Download an image from a given url
async function loadImage(imgUrl) {
  const req = new Request(imgUrl)
  return await req.loadImage()
}


if (config.runsInWidget) {
  Script.setWidget(w)
} else {
  await w.presentSmall()
}

if (config.runsWithSiri) {
  Speech.speak('You have '+followers_total+' followers')
}


Script.complete()