#########################################################################
##                                                                     ##
##  I N T E R S T E L L A R   C O N S O L E  Displaying Date Time      ##
##            Copyright (C) 2025- Misato Observatory, Wakayama, Japan  ##
##                                                                     ##
##  This software is available under the GPL (General Public License)  ##
##                                                                     ##
##  arg is set : for dome screen                                       ##
##  no arg     : for Full-HD display                                   ##
##                                                                     ##
##  Esc key    : exit                                                  ##
##  Space key  : set overrideredirect                                  ##
##  Enter key  : unset overrideredirect                                ##
##  Tab key    : center mark on/off (dome screen only)                 ##
##                                                                     ##
#########################################################################


####################################################################
##                                                                ##
##                       P R O C E D U R E S                      ##
##                                                                ##
####################################################################

#
# サーバURL, ディレクトリ
#
source local-config.tcl

#
# 基本的procをインポートする
#
source -encoding $TCLSRC_ENCODING base-proc.tcl

#
# 日付/時刻スクリーン表示専用
#  in: すべての引数
#
proc draw_on_screen { top layer_id orientation asarr_geom date_string time_string } {

  global radius_for_placing_chars
  global angle_between_two_chars
  global text_foreground_day
  global text_foreground_night
  global font_datetime
  global flag_config_mode
  global flag_draw_grid
  global radius_shadow
  global angle_shadow

  # 配列のために upvar を使っているが、書き換える事はない
  upvar $asarr_geom asarr_geom_ref

  set width_datetime $asarr_geom_ref(WIDTH_DATETIME)
  set height_datetime $asarr_geom_ref(HEIGHT_DATETIME)
  set horizontal_center $asarr_geom_ref(HORIZONTAL_CENTER)
  set vertical_offset $asarr_geom_ref(VERTICAL_OFFSET)

  #
  # 色を計算
  #

  # 0 ... 色変化なし
  # 1 ... 色変化あり (ただし、日没・薄明時刻は関西仕様)
  set flag_use_color_for_day 0

  # 関西仕様           N.A Jan Feb Mar Apr Mar 
  # around sunset
  set time_low_list  { 0.0 5.2 5.7 6.1 6.5 7.0 7.2 7.2 6.8 6.1 5.5 5.0 4.9 }
  # around night-begin
  set time_high_list { 0.0 6.6 7.1 7.5 8.0 8.5 8.9 8.9 8.2 7.5 6.7 6.3 6.3 }

  if { $flag_use_color_for_day != 0 } {

    # "0000-01-01" -> "0-1-1"
    set date_str [regsub -all {0*(\d+)} $date_string {\1}]
    # split
    set date_list [split $date_str "-"]
    set date_m [lindex $date_list 1]

    # "0000-01-01" -> "0-1-1"
    set time_str [regsub -all {0*(\d+)} $time_string {\1}]
    # split
    set time_list [split $time_str ":"]
    set time_h [lindex $time_list 0]
    set time_m [lindex $time_list 1]

    set time_diff [expr abs(($time_h + ($time_m / 60.0)) - 12.0)]

    set time_low [lindex $time_low_list $date_m]
    set time_high [lindex $time_high_list $date_m]
    if { $time_high <= $time_diff } {
      set s $text_foreground_night
      set text_foreground [format "#%02x%02x%02x" [lindex $s 0] [lindex $s 1] [lindex $s 2]]
    } elseif { $time_diff <= $time_low } {
      set s $text_foreground_day
      set text_foreground [format "#%02x%02x%02x" [lindex $s 0] [lindex $s 1] [lindex $s 2]]
    } else {
      set s0 $text_foreground_day
      set s1 $text_foreground_night
      set time_ix [expr  ($time_diff - $time_low) / ($time_high - $time_low)]
      set red [expr int([lindex $s0 0] - ([lindex $s0 0] - [lindex $s1 0]) * $time_ix)]
      set green [expr int([lindex $s0 1] - ([lindex $s0 1] - [lindex $s1 1]) * $time_ix)]
      set blue [expr int([lindex $s0 2] - ([lindex $s0 2] - [lindex $s1 2]) * $time_ix)]
      set text_foreground [format "#%02x%02x%02x" $red $green $blue]
    }

  } else {

    set s $text_foreground_night
    set text_foreground [format "#%02x%02x%02x" [lindex $s 0] [lindex $s 1] [lindex $s 2]]

  }

  #
  # 座標を計算、描画
  #

  set r [expr $radius_for_placing_chars * 1.0]
  set r_shadow [expr ($radius_for_placing_chars + $radius_shadow) * 1.0]

  set m_pai [expr acos(-1.0)]

  set font_test {"Vardana" 80}
  set x_center [expr $width_datetime * 0.5]
  set y_center [expr $height_datetime * 0.5]

  $top.c$layer_id delete all

  if { $flag_config_mode != 0 } {
    if { $layer_id == 0 } {
      $top.c0 create text $x_center $y_center -fill $text_foreground -font $font_test -text "I" -anchor center -justify center -angle 45
      $top.c0 create text $x_center $y_center -fill $text_foreground -font $font_test -text "I" -anchor center -justify center -angle 135
    } else {
      $top.c1 create text $x_center $y_center -fill $text_foreground -font $font_test -text "I" -anchor center -justify center -angle 0
      $top.c1 create text $x_center $y_center -fill $text_foreground -font $font_test -text "I" -anchor center -justify center -angle 90
    }
  }

  if { $flag_draw_grid != 0 } {
    if { $layer_id == 0 } {
      $top.c0 create line $x_center 0 $x_center $height_datetime -fill $text_foreground
      $top.c0 create line 0 $y_center $width_datetime $y_center -fill $text_foreground
    } else {
      $top.c1 create line $x_center 0 $x_center $height_datetime -fill $text_foreground
      $top.c1 create line 0 $y_center $width_datetime $y_center -fill $text_foreground
    }
  }

  #
  if { $orientation == 3 } {
    set flg_sw0 0
    set flg_sw1 1
    set chr_sign 1.0
    set drw_sign -1.0
    set chr_rot 270.0
  } elseif { $orientation == 2 } {
    set flg_sw0 1
    set flg_sw1 0
    set chr_sign -1.0
    set drw_sign -1.0
    set chr_rot 180.0
  } elseif { $orientation == 1 } {
    set flg_sw0 0
    set flg_sw1 1
    set chr_sign -1.0
    set drw_sign 1.0
    set chr_rot 90.0
  } else {
    set flg_sw0 1
    set flg_sw1 0
    set chr_sign 1.0
    set drw_sign 1.0
    set chr_rot 0.0
  }

  #
  set len_date_string [string length $date_string]
  for {set idx 0} {$idx < $len_date_string} {incr idx} {

    set ch [string index $date_string $idx]
    set i [expr $chr_sign * (-4 - $len_date_string + $idx)]
    set theta [expr $i * $angle_between_two_chars]
    set rad_theta [expr $m_pai * $theta / 180.0]
    set rad_theta_shd [expr $m_pai * ($theta + ($chr_sign * $angle_shadow)) / 180.0]
    set chr_theta [expr ($chr_sign * $theta) + $chr_rot]
    set x0 [expr $horizontal_center + ($r * sin($rad_theta))]
    set y0 [expr $drw_sign * (($r * cos($rad_theta)) - $r) + $vertical_offset]
    set x [expr $x0 * $flg_sw0 + $y0 * $flg_sw1]
    set y [expr $y0 * $flg_sw0 + $x0 * $flg_sw1]
    #
    set x0_shd [expr $horizontal_center + ($r_shadow * sin($rad_theta_shd))]
    set y0_shd [expr $drw_sign * (($r_shadow * cos($rad_theta_shd)) - $r) + $vertical_offset]
    set x_shd [expr $x0_shd * $flg_sw0 + $y0_shd * $flg_sw1]
    set y_shd [expr $y0_shd * $flg_sw0 + $x0_shd * $flg_sw1]
    #
    $top.c$layer_id create text $x_shd $y_shd -fill "#101010" -font $font_datetime -anchor center -justify center -text $ch -angle $chr_theta
    $top.c$layer_id create text $x $y -fill $text_foreground -font $font_datetime -anchor center -justify center -text $ch -angle $chr_theta

  }

  #                  1 2 : 3 5 : 5 9
  set lst_time [list 0 1 2 3 4 5 6 7]
  foreach idx $lst_time {

    set ch [string index $time_string $idx]
    set i [expr $chr_sign * (5 + $idx)]
    set theta [expr $i * $angle_between_two_chars]
    set rad_theta [expr $m_pai * $theta / 180.0]
    set rad_theta_shd [expr $m_pai * ($theta + ($chr_sign * $angle_shadow)) / 180.0]
    set chr_theta [expr ($chr_sign * $theta) + $chr_rot]
    set x0 [expr $horizontal_center + ($r * sin($rad_theta))]
    set y0 [expr $drw_sign * (($r * cos($rad_theta)) - $r) + $vertical_offset]
    set x [expr $x0 * $flg_sw0 + $y0 * $flg_sw1]
    set y [expr $y0 * $flg_sw0 + $x0 * $flg_sw1]
    #
    set x0_shd [expr $horizontal_center + ($r_shadow * sin($rad_theta_shd))]
    set y0_shd [expr $drw_sign * (($r_shadow * cos($rad_theta_shd)) - $r) + $vertical_offset]
    set x_shd [expr $x0_shd * $flg_sw0 + $y0_shd * $flg_sw1]
    set y_shd [expr $y0_shd * $flg_sw0 + $x0_shd * $flg_sw1]
    #
    $top.c$layer_id create text $x_shd $y_shd -fill "#101010" -font $font_datetime -anchor center -justify center -text $ch -angle $chr_theta
    $top.c$layer_id create text $x $y -fill $text_foreground -font $font_datetime -anchor center -justify center -text $ch -angle $chr_theta

  }

  if { $layer_id == 0 } {
    $top.pw forget $top.c1
    $top.pw add $top.c0
  } else {
    $top.pw forget $top.c0
    $top.pw add $top.c1
  }

}

#
# 日付/時刻表示用 無限ループ
#
proc show_time { top_a top_b prev_sec } {

  global layer_id
  global display_style
  global stellarium_status_url
  global buffer_date_label
  global buffer_time_label
  global flag_config_mode
  #global nircmd
  global orientation_a
  global asarr_geom_a
  global orientation_b
  global asarr_geom_b

  global flag_update_position

  if { $flag_config_mode != 0 } {
    update_or_create_window $top_a $top_b $display_style
  }

  if { 0 < $flag_update_position } {
    if { 2 < $flag_update_position } {

      if { 0 <= $orientation_a } {
        set s [format "+%d+%d" $asarr_geom_a(POS_X) $asarr_geom_a(POS_Y)]
        wm geometry $top_a $s
      }
      if { 0 <= $orientation_b } {
        set s [format "+%d+%d" $asarr_geom_b(POS_X) $asarr_geom_b(POS_Y)]
        wm geometry $top_b $s
      }

      update

      # This does not work ...
      #set hwnd [winfo id $top]
      #exec -ignorestderr $nircmd win move handle $hwnd $pos_x_for_screen $pos_y_for_screen

      set flag_update_position 0

    }
    incr flag_update_position
  }

  do_http_get $stellarium_status_url line result
  if { $line eq "" } {
    exit
  }

  set status [regexp -- {.*["]local["]:["]([^"T]+)T([^".]+)} $line match date_string time_string]
  if { $status == 1 } {
    set buffer_date_label $date_string
    set buffer_time_label $time_string
    if { $display_style != 0 } {
      if { 0 <= $orientation_a } {
        draw_on_screen $top_a $layer_id $orientation_a asarr_geom_a [format "%11s" $date_string] $time_string
      }
      if { 0 <= $orientation_b } {
        draw_on_screen $top_b $layer_id $orientation_b asarr_geom_b [format "%11s" $date_string] $time_string
      }
      if { $layer_id == 0 } {
        set layer_id 1
      } else {
        set layer_id 0
      }
    }
  }

  set ch_s3 [string index $time_string 3]
  set ch_s2 [string index $time_string 4]
  set ch_s1 [string index $time_string 6]
  set ch_s0 [string index $time_string 7]
  set sec [expr 600 * $ch_s3 + 60 * $ch_s2 + 10 * $ch_s1 + $ch_s0]
  # 可変ウエイト
  if { $flag_config_mode == 0 && 1.0 < abs($sec - $prev_sec) } {
    set wait_msec 100
  } else {
    set wait_msec 500
  }

  after $wait_msec show_time $top_a $top_b $sec

}

#
# Grid表示 切替 (TABキーで呼び出される)
#
proc toggle_center_mark {} {
  global flag_draw_grid
  if { $flag_draw_grid == 0 } {
    set flag_draw_grid 1
  } else {
    set flag_draw_grid 0
  }
}

#
# Screenモード用ウィンドウの作成部 (update_or_create_window から呼ばれる)
#  in:  top orientation font_size
#  out: asarr_geom_ret
#
proc update_or_create_win_for_screen { top orientation font_size asarr_geom_ret } {

  global radius_for_placing_chars
  global angle_between_two_chars

  upvar $asarr_geom_ret asarr_geom_ref

  # create or update window

  catch {destroy $top} wid

  if { 0 <= $orientation } {

    toplevel $top

    set m_pai [expr acos(-1.0)]
    set r [expr $radius_for_placing_chars * 1.0]
    set theta [expr 20 * $angle_between_two_chars]
    set rad_theta [expr $m_pai * $theta / 180.0]
    set w [expr (($r * sin($rad_theta)) + 2 * $font_size) * 2]
    set h [expr ($r - ($r * cos($rad_theta))) + 2 * $font_size]

    if { $orientation == 1 || $orientation == 3 } {
      set width_datetime [format "%.0f" $h]
      set height_datetime [format "%.0f" $w]
      set horizontal_center [format "%.0f" [expr $height_datetime * 0.5]]
      if { $orientation == 3 } {
        set vertical_offset $font_size
      } else {
        set vertical_offset [expr $width_datetime - $font_size]
      }
    } else {
      set width_datetime [format "%.0f" $w]
      set height_datetime [format "%.0f" $h]
      set horizontal_center [format "%.0f" [expr $width_datetime * 0.5]]
      if { $orientation == 2 } {
        set vertical_offset $font_size
      } else {
        set vertical_offset [expr $height_datetime - $font_size]
      }
    }

    # ウィンドゥ属性の設定
    wm resizable $top 0 0

    wm minsize $top $width_datetime $height_datetime
    wm maxsize $top $width_datetime $height_datetime
    wm overrideredirect $top 1
    wm attributes $top -topmost yes
    wm geometry $top ${width_datetime}x${height_datetime}
    wm attributes $top -alpha "1" 
    wm attributes $top -transparentcolor "#000000"

    panedwindow $top.pw -sashwidth 0 -bg "#000000"
    pack $top.pw -expand 1 -fill both

    canvas $top.c0 -width $width_datetime -height $height_datetime
    $top.pw add $top.c0

    canvas $top.c1 -width $width_datetime -height $height_datetime
    $top.pw add $top.c1

    $top.pw forget $top.c1

    bind  $top <Tab> "toggle_center_mark"

    bind $top <Key-space> "wm overrideredirect $top 0"
    bind $top <Return> "wm overrideredirect $top 1"
    bind $top <Escape> "exit"
    bind $top <KeyPress-q> "exit"

    set asarr_geom_ref(WIDTH_DATETIME)    $width_datetime
    set asarr_geom_ref(HEIGHT_DATETIME)   $height_datetime
    set asarr_geom_ref(HORIZONTAL_CENTER) $horizontal_center
    set asarr_geom_ref(VERTICAL_OFFSET)   $vertical_offset

  }

  update

}

#
# ウィンドウの更新or作成
#  in: すべての引数
#
proc update_or_create_window { top_a top_b display_style } {

  global config_file
  global buffer_date_label
  global buffer_time_label
  global date_font_for_virt
  global time_font_for_virt
  global layer_id
  global width_virt
  global height_virt

  global radius_for_placing_chars
  global angle_between_two_chars
  global radius_shadow
  global angle_shadow

  global orientation_a
  global asarr_geom_a
  global orientation_b
  global asarr_geom_b

  global font_datetime

  global flag_update_position

  if { $display_style < 1 } {

    # Displayモード

    # create window
    catch {destroy $top_a} wid
    toplevel $top_a

    # ウィンドゥ属性の設定
    wm resizable $top_a 0 0

    wm minsize $top_a $width_virt $height_virt
    wm maxsize $top_a $width_virt $height_virt
    #wm overrideredirect . 1
    wm overrideredirect $top_a 1
    wm geometry $top_a ${width_virt}x${height_virt}

    label $top_a.l_date -textvariable buffer_date_label -font $date_font_for_virt
    label $top_a.l_time -textvariable buffer_time_label -font $time_font_for_virt

    pack $top_a.l_date $top_a.l_time -expand 1 -fill both

    bind $top_a <Key-space> "wm overrideredirect $top_a 0"
    bind $top_a <Return> "wm overrideredirect $top_a 1"
    bind $top_a <Escape> "exit"
    bind $top_a <KeyPress-q> "exit"

  } else {

    # Screenモード

    # default values
    array set asarr_conf {
      FONT_SIZE 24
      RADIUS_FOR_PLACING_CHARS 1630
      ANGLE_BETWEEN_TWO_CHARS 1.2
      RADIUS_FOR_SHADOW 1.5
      ANGLE_FOR_SHADOW 0.07
      ORIENTATION_A -1
      POS_X_FOR_SCREEN_A +50
      POS_Y_FOR_SCREEN_A +100
      ORIENTATION_B -1
      POS_X_FOR_SCREEN_B +50
      POS_Y_FOR_SCREEN_B +100
    }

    set maxlencol 0
    set ret_text ""
    set status [load_text_file $config_file ret_text maxlencol]
    if { $status == 0 } {
      set lines [split $ret_text "\n"]
      for {set i 0} {$i < [llength $lines]} {incr i} {
        set s [string trim [lindex $lines $i]]
        if { [string length $s] != 0 && [string index $s 0] ne "#" } {
          set lst [split $s "="]
          if { [llength $lst] == 2 } {
            set k [string trim [lindex $lst 0]]
            set v [string trim [lindex $lst 1]]
            set asarr_conf($k) $v
          }
        }
      }
    }

    set flag_updated 0
    set flag_updated_pos 0

    set font_size [lindex $font_datetime 1]
    if { $font_size != $asarr_conf(FONT_SIZE) } {
      set font_size $asarr_conf(FONT_SIZE)
      lset font_datetime 1 $font_size
      set flag_updated 1
    }
    if { $radius_for_placing_chars != $asarr_conf(RADIUS_FOR_PLACING_CHARS) } {
      set radius_for_placing_chars $asarr_conf(RADIUS_FOR_PLACING_CHARS)
      set flag_updated 1
    }
    if { $angle_between_two_chars != $asarr_conf(ANGLE_BETWEEN_TWO_CHARS) } {
      set angle_between_two_chars $asarr_conf(ANGLE_BETWEEN_TWO_CHARS)
      set flag_updated 1
    }
    if { $radius_shadow != $asarr_conf(RADIUS_FOR_SHADOW) } {
      set radius_shadow $asarr_conf(RADIUS_FOR_SHADOW)
      set flag_updated 1
    }
    if { $angle_shadow != $asarr_conf(ANGLE_FOR_SHADOW) } {
      set angle_shadow $asarr_conf(ANGLE_FOR_SHADOW)
      set flag_updated 1
    }
    if { -1 <= $orientation_a } {
      if { $orientation_a ne $asarr_conf(ORIENTATION_A) } {
        set orientation_a $asarr_conf(ORIENTATION_A)
        set flag_updated 1
      }
      if { $asarr_geom_a(POS_X) != $asarr_conf(POS_X_FOR_SCREEN_A) } {
        set asarr_geom_a(POS_X) $asarr_conf(POS_X_FOR_SCREEN_A)
        set flag_updated_pos 1
      }
      if { $asarr_geom_a(POS_Y) != $asarr_conf(POS_Y_FOR_SCREEN_A) } {
        set asarr_geom_a(POS_Y) $asarr_conf(POS_Y_FOR_SCREEN_A)
        set flag_updated_pos 1
      }
    }
    if { -1 <= $orientation_b } {
      if { $orientation_b ne $asarr_conf(ORIENTATION_B) } {
        set orientation_b $asarr_conf(ORIENTATION_B)
        set flag_updated 1
      }
      if { $asarr_geom_b(POS_X) != $asarr_conf(POS_X_FOR_SCREEN_B) } {
        set asarr_geom_b(POS_X) $asarr_conf(POS_X_FOR_SCREEN_B)
        set flag_updated_pos 1
      }
      if { $asarr_geom_b(POS_Y) != $asarr_conf(POS_Y_FOR_SCREEN_B) } {
        set asarr_geom_b(POS_Y) $asarr_conf(POS_Y_FOR_SCREEN_B)
        set flag_updated_pos 1
      }
    }

    if { $flag_updated_pos != 0 } {

      set flag_update_position 999

    }

    if { $flag_updated != 0 } {

      update_or_create_win_for_screen $top_a $orientation_a $font_size asarr_geom_a
      update_or_create_win_for_screen $top_b $orientation_b $font_size asarr_geom_b

      set layer_id 0

      set flag_update_position 1

    }

  }

}


####################################################################
##                                                                ##
##                             M A I N                            ##
##                                                                ##
####################################################################

#
# サーバURL (1)  情報取得用
# 
set stellarium_status_url "$stellarium_url/api/main/status"

# for overrideredirect
option add *highlightThickness "0"

#
# カラー,フォント,ウィンドゥサイズの設定 (Displayモード)
#
option add *background "#000000"
option add *foreground "#d03030"
set date_font_for_virt {"Trebuchet MS" 255}
set time_font_for_virt {"Trebuchet MS" 330}
set width_virt 1920
set height_virt 1080

#
# カラー,フォント,ウィンドゥサイズの設定値 初期化 (Screenモード)
#
set config_file "date-monitor_conf.txt"
#set nircmd "./nircmd.exe"

# 昼用(未使用) "#ffa060"
set text_foreground_day {255 160 96}
# 夜用 "#ff5010"
set text_foreground_night {255 80 16}

set font_datetime {"Vardana" 0 "bold"}

set radius_for_placing_chars 0
set angle_between_two_chars 0
set radius_shadow 1.5
set angle_shadow 0.07

set orientation_a -1
array set asarr_geom_a {
  WIDTH_DATETIME 0
  HEIGHT_DATETIME 0
  HORIZONTAL_CENTER 0
  VERTICAL_OFFSET 0
  POS_X 0
  POS_Y 0
}
set orientation_b -1
array set asarr_geom_b {
  WIDTH_DATETIME 0
  HEIGHT_DATETIME 0
  HORIZONTAL_CENTER 0
  VERTICAL_OFFSET 0
  POS_X 0
  POS_Y 0
}

set flag_update_position 0

# 調整モード
set flag_config_mode 0

# Grid表示を使うか
set flag_draw_grid 0

# 初期値
set buffer_date_label "+0000-00-00"
set buffer_time_label "12:00:00"

# 動作切り替えスイッチ
#
# 0: Displayモード ... 日付・時刻を上下に並べる (大型モニター用)
# 1: Screenモード  ... 日付・時刻を円弧上に表示する (全天周スクリーン用)
#
set display_style 0

# ID of window
set top_a ".topwin_a"
set top_b ".topwin_b"
set layer_id 0

# hide default wish window
wm state . withdrawn

if { 0 < $argc } {

  set display_style 1
  set pid_file ""

  # Screenモードでのパラメータ設定

  if { 0 < $argc } {
    set arg [lindex $argv 0]
    if { $arg eq "config" } {
      set flag_config_mode 1
      set flag_draw_grid 0
    } elseif { $arg eq "grid" } {
      set flag_config_mode 1
      set flag_draw_grid 1
    } elseif { $arg eq "a" } {
      # disable Clock B
      set orientation_b -2
    } elseif { $arg eq "b" } {
      # disable Clock A
      set orientation_a -2
    }
  }

  if { 1 < $argc } {
    # マルチバイト文字が文字化けするので、2つめの引数は使わないこと
    set pid_file [lindex $argv 1]
  } else {
    set pid_file [get_stellarium_io_directory]
    append pid_file "/_tmp_date-monitor_pid.isc.txt"
  }

  if { $pid_file eq "-" } {
    set pid_file ""
  }

  if { $pid_file ne "" } {
    # PID を取得、保存
    if { [catch {open $pid_file w} fid] } {
      wm state . normal
      tk_messageBox -type ok -icon info -title "ERROR" -message "Unable to save a file: $pid_file"
    } else {
      puts $fid [pid]
      catch {close $fid}
    }
  }

}

if { $flag_config_mode == 0 } {
  update_or_create_window $top_a $top_b $display_style
}

# display main window
#wm state . normal

# 無限ループ
show_time $top_a $top_b "00"

