/*
A widget that displays a counter and growth chart, powered by your ilo.so dashboard.

You will need to put in your counter ID in the widget's Parameter field.
You can find your counter ID by clicking the ↗ Share icon in your ilo account.

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

Version 1.1.0 (November 11, 2024)
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 chartOpacity = 0.1

const colors = {
  light: {
    widgetBgColor: "#ffffff", // White
    chartColor: "#666666", // Dark grey
    usernameColor: '#888888', // Grey
    followersColor: '#111111', // Almost black
    dailyChangeColor: '#888888', // Grey
  },
  dark: {
    widgetBgColor: "#222222", // Almost black
    chartColor: "#cccccc", // Light grey
    usernameColor: '#bbbbbb', // Grey
    followersColor: '#eeeeee', // Almost white
    dailyChangeColor: '#bbbbbb', // Grey
  }
}


function getColors() {
  let appearance = (isUsingDarkAppearance()) ? 'dark' : 'light'
  console.log(appearance)
  return colors[appearance]
}


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

let counterId = args.widgetParameter
let url = "https://api.ilo.so/v2/counters/"+counterId+"/?include=today,info,account,history&days="+daysInChart
let req = new Request(url)
const json = await req.loadJSON()
const count = parseInt(json['count']).toLocaleString()
const today = parseInt(json['today']).toLocaleString()
const chartData = json['history']
const counterName = json['name'].toLowerCase()
const accountName = json['account']['name']

// 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(getColors().widgetBgColor);
w.url = 'https://ilo.so/dashboard/'

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
textUsername = w.addText(accountName)
textUsername.textColor = new Color(getColors().usernameColor);
textUsername.font = smallText;

w.addSpacer(4)


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

w.addSpacer(4)


// Show today's follower change
const followerTodayStr = (today > -1 ? '+' : '') + today + " today"
textChange = w.addText(followerTodayStr)
textChange.textColor = new Color(getColors().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(getColors().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 '+count+' '+counterName)
}

function isUsingDarkAppearance() {
  return !(Color.dynamic(Color.white(),Color.black()).red)
}

Script.complete()