const hyprland = await Service.import("hyprland")
const audio = await Service.import("audio")
const systemtray = await Service.import("systemtray")
import { getIconName } from "./utils.js"
import { NotificationPopups } from "./notificationPopups.js"

const battery = await Service.import('battery')
const powerProfiles = await Service.import('powerprofiles')

const batteryIndicator = Widget.Box({
    visible: battery.available,
    children: battery.available? [
    Widget.Icon().hook(battery, self => {
      const thresholds = [...Array(11).keys()].map( i => i * 10);
      const icon = thresholds.find(threshold => threshold >= battery.percent)
      const charging_name = battery.percent >= 99 ? "charged" : "charging"
      self.icon = battery.charging? `battery-level-${icon}-${charging_name}-symbolic` : `battery-level-${icon}-symbolic`
      self.tooltip_text = `Battery ${battery.percent}%`
      self.class_name = "battery-item";
    }),
  ]: []
})

const sensorsAvailable = await Utils.execAsync(['sensors']).then(() => true).catch(() => false)

const volumeIndicator = Widget.Button({
    on_clicked: () => audio.speaker.is_muted = !audio.speaker.is_muted,
    class_name: "item blue",
    child: Widget.Box({
    children: [
      Widget.Icon().hook(audio.speaker, self => {
            const vol = audio.speaker.volume * 100
            const icon = [
                [101, 'overamplified'],
                [67, 'high'],
                [34, 'medium'],
                [1, 'low'],
                [0, 'muted'],
            ].find(([threshold]) => threshold <= vol)?.[1]

            self.icon = `audio-volume-${icon}-symbolic`
            self.tooltip_text = `Volume ${Math.floor(vol)}%`
      }),
      Widget.Label().hook(audio.speaker, self => {
        const label = `${Math.floor(audio.speaker.volume * 100)}%`
        self.label = audio.speaker.is_muted ? "" : label
        self.css = audio.speaker.is_muted ? "margin-left:0;": "margin-left: 0.7em;"
      })
    ]}),
});

let monitor = 0
for (const mon in hyprland.monitors) {
  if (hyprland.monitors[mon]["id"] < hyprland.monitors[monitor]["id"]) {
    monitor = mon
  }
}

function Clients() {
  const activeId = hyprland.active.client.bind("address")
  const clients = hyprland.bind("clients").as(cl =>
    cl.filter(a => !a.title.includes("rofi")).map(({ address, title, workspace }) =>
    {
        const short_title = title.length > 40 ? title.slice(0, 20) + "..." : title
        return Widget.Box({
          attribute: workspace.id,
          class_name: activeId.as(i => `${i === address ? "focused" : ""}`),
          children: [
            Widget.Icon({
              vexpand: false,
              size: 16,
              className: "app-icon",
              icon: getIconName(hyprland.clients.find(c => c.address === address))
            }),
            Widget.Label(`${short_title}`)
          ],
        })
      })
  )

  return Widget.Box({
    class_name: "clients",
    children: clients,
    setup: self => self.hook(hyprland, () => self.children.forEach(box => {
      box.visible = hyprland.active.workspace.id === box.attribute
    })),
  })
}

function Workspaces() {
  const activeId = hyprland.active.workspace.bind("id")
  const workspaces = hyprland.bind("workspaces").as(ws => {
    ws.sort((a, b) => a.id - b.id)
    return ws.map(({ id, monitorID }) =>
      Widget.Button({
        attribute: monitorID,
        label: `${id}`.slice(-1),
        onClicked: () => hyprland.messageAsync(`dispatch workspace ${id}`),
        class_name: activeId.as(i => `${i === id ? "focused" : ""}`),
      })
    )
  })

  return Widget.Box({
    children: workspaces,
    class_name: "workspaces",
    setup: self => self.hook(hyprland, () => self.children.forEach(btn => {
      btn.visible = hyprland.active.monitor.id === btn.attribute
    })),
  })
}

function SysTray() {
  const items = systemtray.bind("items")
  .as(items => items.map(item => {
    return Widget.Button({
    child: Widget.Icon({
      icon: item.bind("icon"),
      class_name: "systray-item",
    }),
    on_primary_click: (_, event) => item.activate(event),
    on_secondary_click: (_, event) => item.openMenu(event),
    tooltip_markup: item.bind("tooltip_markup"),
    class_name: "systray",
  })}
  ))

  return Widget.Box({
    children: items,
  })
}

function Left() {
  return Widget.Box({
    spacing: 8,
    children: [
      Clients(),
    ],
  })
}

function Center() {
  return Widget.Box({
    spacing: 8,
    children: [
      Workspaces(),
    ],
  })
}

function Icons() {
  return Widget.Box({
    spacing: 0,
    class_name: "item icon-group",
    children: [
      SysTray(),
      batteryIndicator,
    ],
  })
}

function Right() {
  return Widget.Box({
    hpack: "end",
    spacing: 8,
    class_name: "right",
    children: [
      Icons(),
      volumeIndicator,
      Widget.Box({
        class_name: "item",
        children: [
          Widget.Icon({
            vexpand: false,
            size: 16,
            icon: "speedometer",
            css: "margin-right: 0.7em;",
          }),
          Widget.Label({
            label: Variable("", {
              poll: [2000, 'top -b -n 1', out => out.split('\n')
                .find(line => line.includes('Cpu(s)'))
                .split(/\s+/)[1]
                .replace(',', '.').toString() + "%"],
            }).bind()
          })
        ]}),
      Widget.Label({
        class_name: "item blue",
        label: Variable("", {
          poll: [2000, 'free', out => (out.split('\n')
            .find(line => line.includes('Mem:'))
            .split(/\s+/)[2] / 1000000).toFixed(2) + "GB"],
        }).bind(),
      }),
      Widget.Button({
        class_name: "item",
        child: Widget.Box({
          children: [
            Widget.Icon({
              vexpand: false,
              size: 16,
              icon: powerProfiles.bind('active_profile').as(profile => `power-profile-${profile}-symbolic`),
              css: "margin-right: 0.7em;",
            }),
            Widget.Label({
              label: Variable("", { poll: [5000, 'bash -c "cat /proc/cpuinfo | grep \\"MHz\\" | awk \'{print \\$4}\' | sort -n | tail -1 | awk \'{printf \\"%.2fGHz\\", \\$1/1000}\'"'] }).bind(),
            }),
          ]
        }),
        on_clicked: () => {
          let next = false
          for (const profile of powerProfiles.profiles) {
            if (next) {
              powerProfiles.active_profile = profile["Profile"]
              return
            } else if (profile["Profile"] === powerProfiles.active_profile) {
              next = true
            }
          }
          powerProfiles.active_profile = powerProfiles.profiles[0]["Profile"]
        },
      }),
      Widget.Label({
        class_name: "item blue",
        label: sensorsAvailable ? Variable("", {
          poll: [5000, 'sensors', out => {
            const match = out.split('\n').find(line => line.includes('Tctl') || line.includes('Package'))?.match(/[0-9.]*°C/);
            return match ? match[0] : "N/A";
          }],
        }).bind() : "N/A",
      }),
      Widget.Button({
        class_name: "item",
        child: Widget.Label({
          label: Variable("", { poll: [1000, 'date "+%Y-%m-%d"'] }).bind(),
        }),
        on_clicked: () => Utils.execAsync(['gnome-calendar']),
      }),
      Widget.Label({
        class_name: "item blue",
        label: Variable("", { poll: [1000, 'date "+%H:%M:%S"'] }).bind(),
      })
    ],
  })
}

function Bar(monitor = 0) {
  return Widget.Window({
    name: `ags-bar-${monitor}`, // name has to be unique
    class_name: "bar",
    monitor,
    anchor: ["top", "left", "right"],
    exclusivity: "exclusive",
    css: "font-size: " + (hyprland.monitors[monitor]["width"] > 2600? "1.2em;": "1em;"),
    child: Widget.CenterBox({
      class_name: "window-box",
      start_widget: Left(),
      center_widget: Center(),
      end_widget: Right(),
    }),
  })
}

print(JSON.stringify(monitor))
App.config({
  style: "./style.css",
  iconTheme: "Papirus",
  windows: [
    Bar(monitor),
    NotificationPopups(),
  ],
})
export { }