#!/usr/bin/env bash

hostname=$(hostname)

hc() { herbstclient "$@" ;}
panel_height=20

for monitor in $(hc list_monitors | cut -d: -f1); do
  hc pad "$monitor" "$panel_height" 0 0 0
done

{ sleep 1; exec trayer --SetPartialStrut false --edge top --height 20 --widthtype request --align right --tint 0x080808 --transparent true --alpha 0; } &

fggreen='%{F#a6e3a1}'
fgblue='%{F#89b4fa}'
fgred='%{F#f38ba8}'
fgdark='%{F#313244}'
fgend='%{F-}'

bggreen='%{B#a6e3a1}'
bgblue='%{B#89b4fa}'
bgred='%{B#f38ba8}'
bglight='%{B#313244}'
bgend='%{B-}'

ulblue='%{U#89b4fa+u}'
ulend='%{-u}'

handle_signal() {
  FORCE_REFRESH=1
}

handle_kill() {
  kill 0
  rm "$fifo"
  exit 0
}

trap handle_signal SIGUSR1
trap handle_kill SIGINT

fifo="/tmp/panel_text"
if [ ! -p "$fifo" ]; then
  mkfifo "$fifo"
fi

msgfifo="/tmp/panel_msg"
if [ ! -p "$msgfifo" ]; then
  mkfifo "$msgfifo"
fi

# process to handle lemonbar clicks
{
  while IFS= read -r line; do
    IFS="-" read -r -a command <<< "$line"
    if [ "${command[0]}" = "tag" ]; then
      # not sure how to specify a monitor, but probably don't need to anyway
      monitor="${command[1]}"
      index=$(( "${command[2]}" - 1 ))
      if [ "$index" -eq -1 ]; then
        index=9
      fi
      herbstclient chain , lock , focus_monitor "$monitor" , use_index "$index" , spawn stickyctl get-sticky , unlock
    fi
  done < "$msgfifo"
} &

tail -f "$fifo" | stdbuf -oL lemonbar -d -p -a 100 -g "x${panel_height}" -f "Drafting* Mono:pixelsize=18:antialias=true" -f "Unifont:pixelsize=18:antialias=true" -B "#11111b" -F "#cdd6f4" > "$msgfifo" &

append_segment() {
  local seconds=$1
  local name=$2
  local param=$3
  shift
  local now=$SECONDS
  local escparam
  segment_text=''

  escparam="${param//\//_}"
  eval "local lastrun=\$${name}${escparam}_lastrun"
  if [ -z "$lastrun" ]; then
    lastrun=0
  fi
  if [ -n "$FORCE_REFRESH" ] || [ "$lastrun" -eq 0 ] || (( SECONDS - lastrun >= seconds )); then
    "$@"
    eval "${name}${escparam}_lastrun=\$now"
    eval "${name}${escparam}_lastoutput=\"$segment_text\""
    panel_text="$panel_text$segment_text"
  else
    eval "panel_text=\"\$panel_text\$${name}${escparam}_lastoutput\""
  fi
}

append_separator() {
  panel_text="$panel_text  "
}

append_percent_icon() {
  local pct=$1
  segment_text="$segment_text$bglight"
  if (( pct < 12 )); then
    segment_text="$segment_text▁"
  elif (( pct < 25  )); then
    segment_text="$segment_text▂"
  elif (( pct < 38 )); then
    segment_text="$segment_text▃"
  elif (( pct < 51 )); then
    segment_text="$segment_text▄"
  elif (( pct < 64 )); then
    segment_text="$segment_text▅"
  elif (( pct < 77 )); then
    segment_text="$segment_text▆"
  elif (( pct < 90 )); then
    segment_text="$segment_text▆"
  else
    segment_text="$segment_text█"
  fi
  segment_text="$segment_text$bgend%{O5}"
}

append_battery_icon() {
  local pct=$1
  segment_text="$segment_text$bglight"
  if (( pct < 10 )); then
    segment_text="$segment_text"
  elif (( pct < 20  )); then
    segment_text="$segment_text"
  elif (( pct < 30 )); then
    segment_text="$segment_text"
  elif (( pct < 40 )); then
    segment_text="$segment_text"
  elif (( pct < 50 )); then
    segment_text="$segment_text"
  elif (( pct < 60 )); then
    segment_text="$segment_text"
  elif (( pct < 70 )); then
    segment_text="$segment_text"
  elif (( pct < 80 )); then
    segment_text="$segment_text"
  elif (( pct < 90 )); then
    segment_text="$segment_text"
  else
    segment_text="$segment_text"
  fi
  segment_text="$segment_text$bgend%{O5}"
}

segment_tags() {
  local monitor=$1
  local tags
  local prefix
  local tagclass

  IFS=$'\t' read -ra tags <<< "$(hc tag_status "$monitor")"
  segment_text=''
  for i in "${tags[@]}"; do
    prefix=${i:0:1}
    case $prefix in
      '.') tagclass=$fgend$bgend ;;
      '+') tagclass=$bgblue$fgdark ;;
      '#') tagclass=$bggreen$fgdark ;;
      '!') tagclass=$bgred$fgdark ;;
      '-') tagclass=$ulblue$bglight$fgblue ;;
      '%') tagclass=$ulblue$bglight$fgblue ;;
      *) tagclass=$bglight ;;
    esac
    segment_text="$segment_text%{A:tag-$monitor-${i:1}:}$tagclass%{O8}${i:1}%{O8}%{A}$fgend$bgend$ulend"
  done
}

segment_timew() {
  local curday
  local active
  local twclass
  local twicon

  if hash timew 2>/dev/null; then
    active=$(timew get dom.active)
    if [ "$active" = "1" ]; then
      twicon=""
      twclass=$fggreen
    else
      twicon=""
      twclass=$fgred
    fi

    curday=$(timew summary | tail -n2 | head -n1 | awk '{ print $1 }')
    if [ "$curday" = "No" ]; then
      curday='0:00'
    else
      curday="${curday%:*}"
    fi

    segment_text="${twclass}${twicon}${fgend}%{O5}$curday"
  fi
}

segment_keyboard() {
  local kblayout
  local kbclass
  local kbicon

  kblayout=$(setxkbmap -query | grep variant | awk '{ print $2 }' | tr -d ',')
  if [ "$kblayout" = "dvorak" ]; then
    kbclass=$fgred
    kbicon=""
  else
    kbclass=$fggreen
    kbicon=""
  fi
  segment_text="$kbclass$kbicon$fgend"
}

segment_network() {
  local net
  local neticon
  local btpower
  local btconn
  local bticon
  local nasavpn
  local nasaicon

  # network device
  net=$(ip route get 1.1.1.1 | grep -Po '(?<=dev\s)\w+' | cut -f1 -d ' ')
  if ! [ "$net" ]; then
    neticon="%{O3}$fgred$fgend"
  else
    neticon="%{O3}$fggreenﯱ$fgend"
  fi

  if hash bluetoothctl 2>/dev/null; then
    # bluetooth status
    btpower=$(bluetoothctl show | grep Powered | awk '{ print $2 }')
    if [ "$btpower" = "yes" ]; then
      btconn=$(bluetoothctl devices | cut -f2 -d' ' | while read uuid; do bluetoothctl info $uuid; done | grep "Connected: yes")
      if [ -z "$btconn" ]; then
        bticon="${fggreen}$fgend"
      else
        bticon="${fgblue}$fgend"
      fi
    else
      bticon="${fgred}$fgend"
    fi
  fi

  if hash docker 2>/dev/null; then
    nasavpn=$(docker ps --format "{{.Names}}" | grep nasavpn)
    if [ -n "$nasavpn" ]; then
      nasaicon="%{O3}${fggreen}異$fgend"
    else
      nasaicon="%{O3}${fgred}異$fgend"
    fi
  fi

  segment_text="$bticon$nasaicon$neticon"
}

segment_memory() {
  local mempct
  local memclass

  mempct=$(free | grep Mem | awk '{ print int($3/$2 * 100.0 + 0.5) }')
  if [ "$mempct" -gt 75 ]; then
    memclass=$fgred
  elif [ "$mempct" -gt 50 ]; then
    memclass=$fgblue
  else
    memclass=$fggreen
  fi
  segment_text=$memclass
  append_percent_icon "$mempct"
  segment_text="${segment_text}$fgend"
}

segment_disk() {
  local dpath=$1
  local diskpct
  local diskclass
  local diskicon

  if [ "$dpath" = "/" ]; then
    diskicon=""
  else
    diskicon=""
  fi

  diskpct=$(df --output=pcent "$dpath" | sed 1d | sed 's/^[ \t]*//' | sed 's/%.*//')
  if [ "$diskpct" -gt 90 ]; then
    diskclass=$fgred
  elif [ "$diskpct" -gt 75 ]; then
    diskclass=$fgblue
  else
    diskclass=$fggreen
  fi
  segment_text=$diskclass
  append_percent_icon "$diskpct"
  segment_text="${segment_text}$diskicon$fgend"
}

segment_cpu() {
  local cpupct
  local cpuclass

  cpupct=$(awk '{u=$2+$4; t=$2+$4+$5; if (NR==1){u1=u; t1=t;} else print ($2+$4-u1) * 100 / (t-t1); }' <(grep 'cpu ' /proc/stat) <(sleep 1;grep 'cpu ' /proc/stat) | awk '{print int($1+0.5)}')
  if [ "$cpupct" -gt 90 ]; then
    cpuclass=$fgred
  elif [ "$cpupct" -gt 25 ]; then
    cpuclass=$fgblue
  else
    cpuclass=$fggreen
  fi
  segment_text=$cpuclass
  append_percent_icon "$cpupct"
  segment_text="${segment_text}$fgend"
}

segment_audio() {
  local audiohdmi
  local audiobt
  local audicon
  local volpct

  if hash pactl 2>/dev/null; then
    # audio output device (hdmi/analog)
    audiohdmi=$(pactl get-default-sink | grep hdmi)
    audiobt=$(pactl get-default-sink | grep bluez)
  fi

  if [ -n "$audiobt" ]; then
    audclass=$fgblue
    audicon='﫽'
  else
    audclass=$fggreen
    if [ "$hostname" != "ellison" ]; then
      if [ -z "$audiohdmi" ]; then
        audicon=''
      else
        audicon='蓼'
      fi
    else
      audicon='蓼'
    fi
  fi
  if hash pamixer 2>/dev/null; then
    volpct=$(pamixer --get-volume-human | sed 's/%//')
    if [ "$volpct" = "muted" ]; then
      audclass=$fgred
      volpct="0"
    fi
  fi
  segment_text=$audclass
  append_percent_icon "$volpct"
  segment_text="$segment_text$audicon$fgend"
}

segment_battery() {
  local battpct
  local batstat
  local baticon
  local batclass

  if hash upower 2>/dev/null; then
    # battery charge percent
    battpct="$(upower --show-info $(upower --enumerate | grep -i 'BAT') | grep -E "percentage" | awk '{print $2}')"
    battpct="${battpct%\%}"

    # battery status (charging/charged/etc)
    batstat="$(upower --show-info $(upower --enumerate | grep -i 'BAT') | grep -E "state" | awk '{print $2}')"

    if (( battpct > 80 )); then
      batclass=$fggreen
    elif (( battpct < 20 )); then
      batclass=$fgred
    else
      batclass=$fgblue
    fi

    segment_text="$batclass"

    if [ "$batstat" = "charging" ]; then
      segment_text="${segment_text}"
    elif [ "$batstat" = "fully-charged" ]; then
      segment_text="${segment_text}"
    else
      append_battery_icon "$battpct"
    fi

    segment_text="$segment_text$fgend"
  else
    segment_text="$fggreenﮣ$fgend"
  fi
}

segment_date() {
  segment_text="$(date +$'%a %b %d') $fgblue$(date +$'%H:%M')$fgend"
}

last_text=''
while true; do
  {
    full_text=''
    for monitor in $(herbstclient list_monitors | cut -d: -f1); do
      panel_text="%{S$monitor}%{l}"
      append_segment 0 segment_tags "$monitor"
      panel_text="$panel_text%{l}%{r}"
      append_segment 60 segment_timew
      append_separator
      append_segment 60 segment_keyboard
      append_separator
      append_segment 10 segment_network
      append_separator
      panel_text="$panel_text%{A:conky:}"
      append_segment 10 segment_memory
      append_separator
      append_segment 60 segment_disk "/"
      append_separator
      if [ "$hostname" != "ellison" ]; then
        append_segment 60 segment_disk "/home"
        append_separator
      fi
      append_segment 5 segment_cpu
      append_separator
      append_segment 60 segment_audio
      append_separator
      append_segment 30 segment_battery
      panel_text="$panel_text%{A}"
      append_separator
      append_segment 60 segment_date
      if [ "$monitor" -eq 0 ]; then
        tray_width=$(xdotool search --classname panel | xargs -n1 xprop -id | grep 'program specified minimum size' | cut -d ' ' -f 5)
        tray_width=$(( tray_width + 5 ))
        panel_text="$panel_text%{O$tray_width}"
      fi
      panel_text="$panel_text%{r}"
      full_text="$full_text$panel_text"
    done
    if [ "$full_text" != "$last_text" ]; then
      echo -e "$full_text"
      last_text="$full_text"
    fi
  } >> "$fifo"
  unset FORCE_REFRESH
  sleep 1
done
