namespace eval ccu4he {
}

proc stdConfig::ccu4he {} {
  variable node
  variable path
  
  controller syncedprot

  pollperiod 5 5
  obj ccu4flow wr
  prop check ccu4he::writeCmd
  prop write stdSct::complete
  prop read ccu4he::readCmd
  prop enum watching,fill,inactive,manualfill
  
  kids "LHe fill" {
    node fast alias /cc/hf
    node state upd -text    
    node hefull alias /cc/hh
    node helow alias /cc/hl
    node smooth upd
  }
}

proc ccu4he::writeCmd {} {
  switch -- [sct target] {
    0 { # watching
      cc hcd 0
      cc ha 1
    }
    1 - 3 { # fill / manualfill
      cc hf 1
      cc hcd 1
      cc ha 1
      sct smooth [silent 10 hval /cc/h]
    }
    2 { # inactive
      cc hcd 0
      cc ha 0
    }
  }
  hupdate [sct]/status ""
  sct update [sct target]
}

proc ccu4he::readCmd {} {
  set stxt ""
  switch -- [hvali /cc/hsf] {
    1 {
      set stxt " / LHe sensor warm"
    }
    2 {
      set stxt " / no LHe sensor connected"
    }
    3 {
      set stxt " / LHe measure timeout"
    }
    4 {
      set stxt " / LHe sensor not yet read"
    }
    default {
    }
  }
  if {[sctval [sct]] == 3} { # manual fill
    cc hf 1
    cc hcd 1
    cc ha 1
    updateval [sct]/state manual_fill$stxt
    return idle
  }
  set level [hval /cc/h]
  if {[sctval [sct]] == 1} { # filling
    set full_level [hval /cc/hh]
    if {$level < $full_level} {  # else CCU4 will stop
      set now [DoubleTime]
      set delta [expr min(30, $now - [silent $now sct last_time])]
      sct last_time $now
      set smooth [silent $level sct smooth]
      # minimum fill speed: 1 % / 36 sec = 100 % / 60 min
      set smooth [expr $smooth + $delta / 36.0]
      if {$level > $smooth} {
        # maximum fill speed 1/18 %/sec + 1/9 %/sec = 100 % / 10 min
        set smooth [expr $smooth + $delta / 9.0]
      }
      sct smooth $smooth
      catch {
        # test on running system: [sct]/smooth does not yet exist
        hupdate [sct]/smooth $smooth
      }
      if {$smooth > min($full_level, $level + 30)} {
        if {$smooth > $full_level} {
          sct update 0   # watching
          cc hcd 0
          cc ha 1
          clientput "stopped LHe fill at $level %, as projected level [format %.4g $smooth] > $full_level"
        } else {
          sct update 2   # timeout
          cc hcd 0
          cc ha 0
          hupdate [sct]/status "fill timeout: not increasing enough"
          clientput "stopped and disabled LHe fill, as level is not increasing enough"
        }
        return idle
      }
    }
  } elseif {[sctval [sct]] == 0} { # watching
    sct smooth $level
    if {[hval [sct]/status] ne ""} {
      hupdate [sct]/status ""
    }
  }
  switch -- [hvali /cc/hv] {
    0 {
      set txt "fill valve off"
      if {[hvali /cc/hsf] == 2} {  # no sensor
        sct update 2
      } else {
        if {[hvali /cc/ha]} {
          sct update 0
        } else {
          sct update 2
        }
      }
    }
    1 {
      set txt "filling"
      sct update 1
    }
    2 {
      set txt "no fill valve"
      sct update 2
    }
    3 {
      set txt timeout
      sct update 2
    }
    4 {
      set txt timeout1
      sct update 2
    }
    default {
      set txt "unknown error"
      sct update 2
    }
  }
  updateval [sct]/state "$txt$stxt"
  return idle
}
