#########################################################################
##                                                                     ##
##  I N T E R S T E L L A R   C O N S O L E  Media GUI                 ##
##            Copyright (C) 2025- Misato Observatory, Wakayama, Japan  ##
##                                                                     ##
##  This software is available under the GPL (General Public License)  ##
##                                                                     ##
##       Tcl/Tk References: http://www.nct9.ne.jp/m_hiroi/tcl_tk_doc/  ##
##                                                                     ##
#########################################################################

#
# サーバURL, OS依存の定数, GUIの基本設定(フォント,色)をセット
#
source local-config.tcl

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


####################################################################
##                                                                ##
##              G E N E R I C   P R O C E D U R E S               ##
##                                                                ##
####################################################################

#
# ISC用 基本的procをインポートする
#
source isc-proc.tcl

#
# 汎用: stellariumスクリプトn行 を送信 (可変引数)
#
#  【注意】
#    ・args[n] に空白を入れたい場合は [~] を、["] を入れたい場合は ['] とする。
#      例: "Ursa Major" は 'Ursa~Major' とする
#    ・送信できるのは、関数の羅列だけである。
#      Stellariumがクラッシュするため、for()文などの制御構文を送ってはならない。
#
proc send_ssc_lines_mg { args } {

  global stellarium_direct_url
  global buffer_internal_info_mg

  foreach code1line $args {

    # replace [~] with [ ], and ['] with ["]
    set code_p0 [regsub -all {~} $code1line { }]
    set code_p1 [regsub -all {'} $code_p0 {"}]
    set str_code "$code_p1"

    set buffer_internal_info_mg $str_code

    # send a code using POST
    do_http_post $stellarium_direct_url "code=$str_code" ret buffer_internal_info_mg

  }

}

#
# 汎用: ISC Serverから読み込み、1行=1要素の配列を array_ret に返す
#
proc get_line_array_from_iscserv_mg { filename_text array_ret } {

  upvar $array_ret array_ref
  global iscserv_url
  global buffer_internal_info_mg

  array set array_ref {}

  do_http_get $iscserv_url/$filename_text ret_string buffer_internal_info_mg

  if { $ret_string eq "" } {
    # do nothing
  } else {
    set lines [split $ret_string "\n"]
    set len_lines [llength $lines]
    set j 0
    for {set i 0} {$i < $len_lines} {incr i} {
      set txt_line [lindex $lines $i]
      set s [string trim $txt_line]
      # skip comments
      if { [string length $s] != 0 && [string index $s 0] ne "#" } {
        set array_ref($j) $s
        incr j
      }
    }
  }

}


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

#                                        #
# ここからのprocは特定のウィジェット専用 #
#                                        #

# load and display a sky image
proc display_sky_image { image_id } {

  global flag_sky_image
  global name_sky_image
  global param_sky_image
  global checkbox_sky_image

  if { $checkbox_sky_image($image_id) != 0 } {
    send_ssc_lines_mg "core.loadSkyImage($name_sky_image($image_id),$param_sky_image($image_id))"
  } else {
    send_ssc_lines_mg "core.removeSkyImage($name_sky_image($image_id))"
  }

}

# remove all sky images
proc remove_all_sky_images {} {

  global name_sky_image
  global checkbox_sky_image

  set len_names [array size name_sky_image]

  for {set i 0} {$i < $len_names} {incr i} {
    send_ssc_lines_mg "core.removeSkyImage($name_sky_image($i))"
    set checkbox_sky_image($i) 0
  }

}

# build GUI of image list
proc build_sky_image_check_list { filename_text } {

  global font_small
  global stellarium_script_dir
  global config_default_media_dir
  global buffer_internal_info_mg

  global flag_sky_image
  global name_sky_image
  global param_sky_image

  array set flag_sky_image {}
  array set name_sky_image {}
  array set param_sky_image {}

  array set lines {}

  get_line_array_from_iscserv_mg $filename_text lines

  set len_lines [array size lines]

  #set buffer_internal_info_mg "len_lines = $len_lines"
  #set len_lines 0

  for {set i 0} {$i < $len_lines} {incr i} {
    set lst [split $lines($i) ","]
    if { 6 <= [llength $lst] } {
      set s0 [string trim [lindex $lst 0]]
      set s1 [string trim [lindex $lst 1]]
      if { [string match {[A-Za-z]:[/\\]*} $s1] } {
        set path_s1 [regsub -all {[\\]} $s1 "/"]
      } elseif { [string match {[/\\]*} $s1] }  {
        set path_s1 [regsub -all {[\\]} $s1 "/"]
      } else {
        set path_s1 "$stellarium_script_dir/$config_default_media_dir/$s1"
      }
      set s2 [string trim [lindex $lst 2]]
      set s3 [string trim [lindex $lst 3]]
      set s4 [string trim [lindex $lst 4]]
      set s5 [string trim [lindex $lst 5]]
      set s6 [string trim [lindex $lst 6]]
      if { $s6 eq "" } {
        set s6 "0"
      }
      set s7 [string trim [lindex $lst 7]]
      if { $s7 eq "" } {
        set s7 "2.5"
      }
      set s8 [string trim [lindex $lst 8]]
      if { $s8 eq "" } {
        set s8 "-14"
      }
      set flag_sky_image($i) 0
      set name_sky_image($i) "'$s0'"
      set param_sky_image($i) "'$path_s1',$s3,$s4,$s5,$s6,$s7,$s8,true,'$s2'"
      frame .fr_cb_sky_image_$i
      ttk::checkbutton .cb_sky_image_$i -style Small.TCheckbutton -text "$s0" -variable checkbox_sky_image($i) -command "display_sky_image $i"
      label .cl_sky_image_$i -text "($s1, $s2, $s3, $s4, $s5)" -font $font_small
      pack .cb_sky_image_$i -side left -expand 0 -fill x -in .fr_cb_sky_image_$i
      pack .cl_sky_image_$i -expand 1 -fill x -in .fr_cb_sky_image_$i
      pack .fr_cb_sky_image_$i -expand 0 -fill x -in .lf_sky_image
    }
  }
}


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

#
# Host用 GUI かどうかのフラグ (リモートマシンの場合は 0)
#
set flag_host_gui 0

#
# 動作モード
#
set flag_large_gui 0

set flag_copy_only 0

#
# エディタ
#
set flag_external_editor 0

#
# 引数でフラグを設定、サーバURLが与えられる場合は接続先を変更
#
for {set i 0} {$i < $argc} {incr i} {
  set arg [lindex $argv $i]
  if { $arg eq "-host" } {
    set flag_host_gui 1
    set flag_external_editor 1
  } elseif { $arg eq "-large-gui" } {
    set flag_large_gui 1
  } elseif { $arg eq "-copy-only" } {
    set flag_copy_only 1
  } else {
    set status [regexp -- {(http[:][^,]+),(http[:][^,]+)} $arg match url0 url1]
    if { $status == 1 } {
      set stellarium_url "$url0"
      set iscserv_url    "$url1"
    }
  }
}

#
# 画像・動画が格納されるデフォルトのディレクトリ
#
set config_default_media_dir "media"

#
# ファイル名
#
set filename_list_skyimg "list_sky-image.txt"

#
# 色・フォントの設定
#
if { $flag_large_gui == 0 } {
  # Normal GUI モード
  # デフォルト
  option add *font [list $gui_font_name 12]
  set font_small [list $gui_font_name 10]
  # ラベルフレーム
  set font_labelframe [list $gui_font_name 10]
  # 内部情報
  set font_internal [list $gui_font_name 10]
  #
  ttk::style configure TButton -font [list $gui_font_name 12]
  ttk::style configure TButton -padding [scaled_padding 3 3]
  ttk::style configure Small.TButton -font [list $gui_font_name 10]
  ttk::style configure Small.TButton -padding [scaled_padding 2 1]
  # TCheckbutton の padding は標準チェックボタン(padding値はデフォルト)よりわずかに小さくしてある
  ttk::style configure TCheckbutton -font [list $gui_font_name 12] -padding [scaled_padding 8 8]
  ttk::style configure TCheckbutton -indicatordiameter [scaled_px 10]
  ttk::style configure Small.TCheckbutton -font $font_small -padding [scaled_padding 6 6]
} else {
  # Large GUI モード
  # デフォルト
  option add *font [list $gui_font_name 20]
  set font_small [list $gui_font_name 16]
  # ラベルフレーム
  set font_labelframe [list $gui_font_name 12]
  # 内部情報
  set font_internal [list $gui_font_name 10]
  #
  ttk::style configure TButton -font [list $gui_font_name 20]
  ttk::style configure TButton -padding [scaled_padding 12 11]
  ttk::style configure Small.TButton -font [list $gui_font_name 16]
  ttk::style configure Small.TButton -padding [scaled_padding 8 7]
  # TCheckbutton の padding は標準チェックボタン(padding値はデフォルト)よりわずかに小さくしてある
  ttk::style configure TCheckbutton -font [list $gui_font_name 20] -padding [scaled_padding 10 10]
  ttk::style configure TCheckbutton -indicatordiameter [scaled_px 16]
  ttk::style configure Small.TCheckbutton -font $font_small -padding [scaled_padding 8 8]
}


#
# Do not change: Set stellarium_script_dir from localConfig.ssc
#
if { [catch {open "localConfig.ssc" r} fid] } {
  wm state . normal
  tk_messageBox -type ok -icon info -title "ERROR" -message "Cannot open localConfig.ssc."
  exit
} else {
  set stellarium_script_dir "interstellar-console"
  while { [gets $fid line] >= 0 } {
    set status [regexp -- {^[ ]*var[ ]+([A-Za-z0-9_]+)[ ]*[=][ ]*["]([^"]+)["]} $line match s0 s1]
    if { $status == 1 && $s0 eq "stellarium_script_dir" } {
      set stellarium_script_dir $s1
    }
  }
  close $fid
}

#
# サーバURL (1)  サーバ側に保存されているスクリプト(staticなコード)
#                を実行する時に利用
# 
set stellarium_run_url "$stellarium_url/api/scripts/run"

#
# サーバURL (2)  クライアントで生成したスクリプト(dynamicなコード)
#                を送信する時に利用
# 
#   注意: direct を使う場合、実行できるのは１行のみらしい。
#         複数行のコードを送信すると、Stellariumがクラッシュする
set stellarium_direct_url "$stellarium_url/api/scripts/direct"

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


####################################################################
##                                                                ##
##                G U I   C O N S T R U C T I O N                 ##
##                                                                ##
####################################################################

set buffer_internal_info_mg "-"

array set checkbox_sky_image {}
array set flag_sky_image {}
array set name_sky_image {}
array set param_sky_image {}


########################################################################

#
# GUI のオープン
#  top: 新規のtoplevelウィンドウ名。"" の場合は新規に作らず、
#       既存のメインウィンドウを使用する
#  flag_copy_only: 0 以外をセットすると、設定ファイルのコピーのみ実行し、
#                  GUI は作らない（hostの場合のみ）
#
proc open_media_gui { top flag_copy_only } {

  global flag_host_gui
  global stellarium_url
  global iscserv_url
  global config_default_media_dir
  global filename_list_skyimg

  global font_labelframe
  global font_internal
  global buffer_internal_info_mg

  #
  # Host用 GUIの場合、設定ファイルをISC Serverのrootにコピーする
  #
  if { $flag_host_gui != 0 } {

    # ISC Server の root ディレクトリを取得する
    do_http_get $iscserv_url ret buffer_internal_info_mg
    set lst [split [string trim $ret] ","]

    if { 1 < [llength $lst] } {
      set isc_root [string trim [lindex $lst 1]]
      set buffer_internal_info_mg "isc_root=$isc_root"

      # 設定ファイルをコピーする
      set buffer_internal_info_mg "copy: $filename_list_skyimg -> $isc_root/."
      file copy -force $config_default_media_dir/$filename_list_skyimg $isc_root/$filename_list_skyimg
    }

    if { $flag_copy_only != 0 } {
      if { $top eq "" } {
        exit
      }
      return
    }

  }

  set status 0
  if { $top ne "" } {
    set status [catch {toplevel $top} ret]
  }

  if { $status == 0 } {

    # ウィンドゥ名称,属性の設定
    set title_str "Interstellar Console :: media"
    if { $flag_host_gui != 0 } {
      append title_str " (Host)"
    } else {
      append title_str " ($stellarium_url)"
    }

    if { $top eq "" } {
      wm title . $title_str
      wm resizable . 0 0
    } else {
      wm title $top $title_str
      wm resizable $top 0 0
    }

    ########################################################################

    frame $top.fr_rootwin

    ########################################################################

    labelframe $top.lf_sky_image -text "Sky Image" -font $font_labelframe

    frame $top.fr_label_sky_image

    label $top.l_sky_image -text "画像選択"
    ttk::button $top.b_sky_image_aoff -style Small.TButton -text "全Off" -command "remove_all_sky_images"
    ttk::button $top.b_sky_image_edit -style Small.TButton -text "編集" -command "open_text_editor .edt_skim $config_default_media_dir/$filename_list_skyimg"
    pack $top.l_sky_image -side left -expand 1 -fill x -in $top.fr_label_sky_image
    pack $top.b_sky_image_aoff -side left -expand 0 -fill x -in $top.fr_label_sky_image
    if { $flag_host_gui != 0 } {
      pack $top.b_sky_image_edit -side left -expand 0 -fill x -in $top.fr_label_sky_image
    }
    pack $top.fr_label_sky_image -expand 0 -fill x -in $top.lf_sky_image

    # ISC Serverから設定ファイルを読んで GUI を構築する
    build_sky_image_check_list $filename_list_skyimg

    pack $top.lf_sky_image -expand 0 -fill x -padx [scaled_px 4] -pady [scaled_px 3] -in $top.fr_rootwin

    ################################################################

    labelframe $top.lf_internal -text "Internal Info" -font $font_labelframe

    entry $top.e_debug -textvariable buffer_internal_info_mg -font $font_internal
    pack $top.e_debug -expand 1 -fill x -in $top.lf_internal

    pack $top.lf_internal -expand 0 -fill x -padx [scaled_px 4] -pady [scaled_px 3] -in $top.fr_rootwin

    ########################################################################

    pack $top.fr_rootwin

  }

  return

}

# hide default wish window
wm state . withdrawn

open_media_gui "" $flag_copy_only

# display main window
wm state . normal

