#!/usr/local/bin/tcl
#
set work_dir /ossc/local/Reserve
source $work_dir/common.tcl
proc MainLoop {} {
  global machines
  set usage  "commands are: (r)eserve (d)elete (s)how (a)dd (c)hange (h)elp (q)uit"
  while {[True]} {
    puts "\nHOSTS: $machines"
    puts $usage
    puts -nonewline "** enter command> "
    gets stdin cmd
    switch $cmd {
      r	{ReserveHost}
      d	{DeleteReservation}
      s	{Display}
      h	{Help}
      a	{AddHost}
      c	{Change}
      q {Quit}
      default	{puts "I don't understand that\n$usage"}
    }
  }
}

proc True {} {
  return 1
}

proc Quit {} {
  global armed_host
  if {$armed_host != ""} {
    puts -nonewline "** You have not save your changes. Are you sure? "
    gets stdin ans
    if {[regexp {[Yy].*} $ans]} {
      exit
    }
  }
  exit
}

proc Help {} {
  puts "type 'r' to make a reservation"
  puts "type 'd' to delete a reservation"
  puts "type 's' to show host stammdaten or reservations"
  puts "type 'a' to add a host to system"
  puts "type 'c' to change host Stammdaten"
}

proc Enter {prompt force default} {
  set done 0
  set def_str ""
  if {[string length $default]} {
    set force 0
    set def_str " \[$default\]"
  }
  while {!$done} {
    puts -nonewline "** $prompt${def_str}: "
    gets stdin buf
    if {$force} {
      if {[string length $buf] > 0} {set done 1}
    } else {
      set done 1
    }
  }
  if {[string length $buf] == 0} {
    return "$default"
  }
  return "$buf"
}

proc GetHalf {} {
  while {[True]} {
    set tmp [Enter {Enter "(m)orning" or "(a)fternoon"} 1 {}]
    switch $tmp {
      m	{return 0}
      a	{return 1}
      default	{puts "haeh?"}
    }
  }
}

proc Dialog {junk1 junk2 message junk3 junk4 junk5} {
  puts "$message"
}

proc YesNo {prompt} {
  while {[True]} {
    puts -nonewline "$prompt \[(y)es/(n)o\] ? "
    gets stdin ans
    switch $ans {
      y	{return 1}
      n	{return 0}
      default	{puts "haeh?"}
    }
  }
}

proc ReserveHost {} {
  global username alarm_minutes armed_host
  set host [Enter {Enter hostname} 0 {}]
  if {![HostExist $host]} {
    puts "the hostname must exist in system."
    return
  }
  if {![RequestLock $host]} {
    return -1
  }
  set armed_host $host
  ReadHostFile $host
  UpdateHostList $host
  puts "You now have two minutes to reserve ${host}..."
  alarm [expr $alarm_minutes * 60]
  set tmp [Enter {Enter starting date in form dd/mm/yy} 0 {}]
  if {$tmp == ""} {
    RelinquishLock $host
    set armed_host ""
    return
  }
  set starthalf [GetHalf]
  set start_hc [ConvertFromFileDate "$tmp/$starthalf"]
  if {$start_hc == ""} {
    puts "error in input"
    RelinquishLock $host
    set armed_host ""
    return -1
  }
  set end [Enter {Enter ending date in form dd/mm/yy} 1 {}]
  if {$end == ""} {return}
  set endhalf [GetHalf]
  set end_hc [ConvertFromFileDate "$end/$endhalf"]
  if {$end_hc == ""} {
    puts "error in input
    RelinquishLock $host
    set armed_host ""
    return -1
  }
  set ret [CheckBits $host $start_hc $end_hc]
  if {$ret == -1} {
    puts "You can't reserve that far ahead"
  } elseif {$ret == 0} {
    puts "This would overlap another reservation"
  } else {
    set cust [Enter {Customer} 0 {}]
    set sonst [Enter {Sonstiges} 0 {}]
    puts "\n---------------------------------"
    puts "host:	$host"
    puts "from:	[Convert nicedate $start_hc]"
    puts "to:	[Convert nicedate $end_hc]"
    puts "kunde:	$cust"
    puts "sonst:	$sonst"
    if {[YesNo "** Confirm the reservation"]} {
      ReserveBits $host $start_hc $end_hc "$username" "$cust" "$sonst"
      LogIt "reserved host $host from [Convert nicedate $start_hc] to\
        [Convert nicedate $end_hc]"
    }
    WriteHostFile $host chgrp
  }
  RelinquishLock $host
  set armed_host ""
  alarm 0.0
}

proc CheckBits {host start end} {
  global biglist
  if {$end >= [llength $biglist($host)]} {return -1}
  for {set i $start} {$i <= $end} {incr i} {
    if {[lindex $biglist($host) $i] > 0} {
      return 0
    }
  }
}

proc RelinquishLock {host} {
  global work_dir lock_file_extension
  cd $work_dir
  set lock_name "${work_dir}/${host}.$lock_file_extension"
  exec rm $lock_name
}

proc HostExist {host} {
  global machines
  if {[lsearch $machines $host] >= 0} {return 1}
  return 0
}

proc ListHostReservations {host} {
  # host assumed to be valid
  global host_reservations
  foreach ent $host_reservations($host) {
    set tag [lindex $ent 0]
    set start [lindex $ent 1]
    set end [lindex $ent 2]
    set user [lindex $ent 3]
    set cust [lindex $ent 4]
    set sonst [lindex $ent 5]
    puts "tag: $tag, from [Convert nicedate $start] to [Convert nicedate $end]\
      by: $user, customer: $cust"
  }
}
  
proc DeleteReservation {} {
  global host_reservations armed_host username
  set host [Enter {Enter hostname} 0 {}]
  if {![HostExist $host]} {
    puts "you must specify an existing host"
    return
  }
  if {![RequestLock $host]} {
    return -1
  }
  set armed_host $host
  ReadHostFile $host
  ListHostReservations $host
  set found 0
  set index 0
  while {!$found} {
    puts -nonewline "** type the tag of the entry to delete: "
    gets stdin ans
    foreach ent $host_reservations($host) {
      set tag [lindex $ent 0]
      if {$tag == $ans} {
        set found 1
        set start [lindex $ent 1]
        set end [lindex $ent 2]
        set user [lindex $ent 3]
        set cust [lindex $ent 4]
        set sonst [lindex $ent 5]
        break
      }
      incr index
    }
  }
  puts "\n---------------------------------"
  puts "host:	$host"
  puts "from:	[Convert nicedate $start]"
  puts "to:	[Convert nicedate $end]"
  puts "user:	$user"
  puts "kunde:	$cust"
  puts "sonst:	$sonst"
  set doit 0
  if {[YesNo "** Confirm delete"]} {
    set doit 1
    if {$username != $user} {
      puts "You did not make this reservation. (a mail will be sent to $user)"
      if {![YesNo "** Really delete"]} {
        Mail $user "$username deleted your reservation for machine\
          $host from [Convert nicedate $start] to [Convert nicedate $end]"
        set doit 0
      }
    }
  }  
  if {$doit} {
    puts "index=$index, start=$start, end=$end"
    set newlist [lreplace $host_reservations($host) $index $index]
    set host_reservations($host) $newlist
    ZeroHostBits $host $start $end
  }
  WriteHostFile $host chgrp
  RelinquishLock $host
  set armed_host ""
}

proc Display {} {
  global machines
  puts "HOSTS: $machines"
  puts -nonewline "** Show (r)eservation or (s)tammdaten? "
  gets stdin ans
  switch $ans {
    r	{DisplayReservation}
    s	{DisplayStammdaten}
    default	{puts "haeh?"; return}
  }
}

proc DisplayReservation {} {
  set host [Enter {Enter hostname} 0 {}]
  if {![HostExist $host]} {
    puts "you must specify an existing host"
    return
  }
  ReadHostFile $host
  ListHostReservations $host
}

proc DisplayStammdaten {} {
  global host_info
  set host [Enter {Enter hostname} 0 {}]
  if {![HostExist $host]} {
    puts "you must specify an existing host"
    return
  }
  set entry $host_info($host)
  puts "\n------------------------------"
  puts "host:		$host"
  puts "hardware:	[lindex $entry 1]"
  puts "memory:		[lindex $entry 2]"
  puts "disks:		[lindex $entry 3]"
  puts "remarks:	[lindex $entry 4]"
}

proc ShowHostInfo {list} {
  puts "\n-----------------------------"
  puts "host:		[lindex $list 0]"
  puts "hw:		[lindex $list 1]"
  puts "mem:		[lindex $list 2]"
  puts "disks:		[lindex $list 3]"
  puts "remarks:	[lindex $list 4]"
  puts "-----------------------------\n"
}
  
proc AddHost {} {
  global machines host_info
  set host [Enter {Enter hostname} 0 {}]
  if {$host == ""} {return}
  set hardware [Enter {hardware} 1 {}]
  set memory [Enter {memory capacity} 1 {}]
  set disks [Enter {disks} 1 {}]
  set remarks [Enter {any remarks} 0 {}]
  ShowHostInfo "{$host} {$hardware} {$memory} {$disks} {$remarks}"
  if {[YesNo "** Confirm"]} {
    lappend machines $host
    set host_info($host) "{$host} {$hardware} {$memory} {$disks} {$remarks}"
    WriteHostFile $host chgrp
  }
}

proc Change {} {
  global host_info alarm_minutes armed_host
  set host [Enter {Enter hostname} 0 {}]
  if {![HostExist $host]} {
    puts "you must specify an existing host"
    return
  }
  if {![RequestLock $host]} {
    return -1
  }
  set armed_host $host
  alarm [expr $alarm_minutes * 60]
  puts "You now have two minutes to make changes..."
  ReadHostFile $host
  ShowHostInfo "$host_info($host)"
  set hard [lindex "$host_info($host)" 1]
  set memory [lindex "$host_info($host)" 2]
  set disks [lindex "$host_info($host)" 3]
  set remarks [lindex "$host_info($host)" 4]
  set hard [Enter {hardware} 0 "$hard"]
  set memory [Enter {memory} 0 "$memory"]
  set disks [Enter {disks} 0 "$disks"]
  set remarks [Enter {remarks} 0 "$remarks"]
  ShowHostInfo "{$host} {$hard} {$memory} {$disks} {$remarks}"
  if {[YesNo "** Confirm Changes"]} {
    set host_info($host) "{$host} {$hard} {$memory} {$disks} {$remarks}"
  }
  WriteHostFile $host chgrp
  RelinquishLock $host
  set armed_host ""
  alarm 0.0
}

proc CleanUp {sig_name} {
  global armed_host lock_file_extension work_dir
  cd $work_dir
  if {$armed_host != ""} {
    set filename "${armed_host}.${lock_file_extension}"
    exec rm $filename
    set armed_host ""
    if {$sig_name == "SIGALRM"} {
      puts "Your time ran out...exiting"
    } else {
      puts "Cleaning up..."
    }
  }
  Quit
}
set num_cells 120
CellBind
InitVirginBiglist
ZeroHostLists
FindHosts
ReadAllHosts
UpdateLists
#puts "num of entries in cell_binding: [llength $cell_binding]"
#puts "num of entries in biglist(alfam5): [llength $biglist(alfam5)]"
signal trap SIGALRM {CleanUp %S}
signal trap SIGINT {CleanUp %S}
MainLoop
