#!/usr/bin/env node

import { Hyprland } from '../../services/hyprland';
import child_process = require('child_process');
import * as lodash from 'lodash';
import * as shelljs from 'shelljs';

type Entry = {
  address: string;
  workspace: string;
  appName: string;
  appTitle: string;
};

async function main() {
  const hyprland = new Hyprland();

  const clients = hyprland.getClients();

  const items: Entry[] = clients
    .filter((client) => client.mapped)
    .map((client) => ({
      address: client.address,
      workspace: String(client.workspace.name),
      appName: client.class || '???',
      appTitle: client.title || '',
    }));

  if (items.length === 0) {
    return;
  }

  const maxWorkspaceLength = items
    .map((item) => item.workspace.length)
    .reduce((prev, curr) => {
      if (prev >= curr) {
        return prev;
      } else {
        return curr;
      }
    });

  const maxAppNameLength = items
    .map((item) => item.appName.length)
    .reduce((prev, curr) => {
      if (prev >= curr) {
        return prev;
      } else {
        return curr;
      }
    });

  const dmenu = lodash
    .sortBy(items, ['appName'])
    .map(
      (item) =>
        `${item.workspace.padEnd(maxWorkspaceLength)} ${item.appName.padEnd(
          maxAppNameLength,
        )} ${item.appTitle} (${item.address})`,
    )
    .join('\n');

  const rofi = child_process.exec(
    'rofi -dmenu -i -p "Select a Window" -format',
  );

  rofi.stdin.write(dmenu);
  rofi.stdin.end();

  let output = '';

  for await (const chunk of rofi.stdout) {
    output += chunk;
  }

  const addressMatch = output.trim().match(/\(0x[0-9a-f]+\)$/);

  if (addressMatch !== null) {
    const address = addressMatch[0].slice(1, -1);
    shelljs.exec(`hyprctl dispatch focuswindow address:${address}`);
  }
}

void main();
