scite_require 'extlib.lua'

local interp_obj=nil
local interp_prompt='? '
-- loading, running, waiting, stopped, exiting
local interp_state='stopped'
local interp_mode=''
local interp_newmode=''
local interp_command=''
local interp_onstop=nil

local last_pos=0
local prev_chunk=''


function InterpProcessChunk(s)
  local p=s:find('\n')
  if interp_mode=='kotlin' then
--- kotlin bug
    if s:sub(1,2)=='\r\n' then
      trace(prev_chunk)
    end
    if not p and (s:sub(-1)==')' or s:sub(-1)=='}' or s:sub(-1)==']' or s:sub(-4)=='... ') then
      prev_chunk=s
      return
    else
      prev_chunk=''
    end
  end

  if p then
    p=s:find('\n[^\n]*$')
    if p then 
      last_pos=s:len()-p
    end
  else
    last_pos=last_pos+s:len()
  end
  trace(s)
  if s:sub(-interp_prompt:len())==interp_prompt then
    interp_state='waiting'
    if interp_command:len()>0 then
      local cmd=interp_command
      interp_command=''
      interp_write(cmd)
    end 
  end
end

function InterpProcessResult(res)
  if interp_state ~= 'stopped' then
    interp_state='stopped'
    trace("Код завершения "..res.."\n")
    if interp_onstop~=nil then
      local onstop=interp_onstop
      interp_onstop=nil
      onstop()
    end
  end
end

function kill_interp()
  if interp_state=='exiting' then
    interp_obj:kill()
    interp_state='stopped'
    if interp_onstop~=nil then
      local onstop=interp_onstop
      interp_onstop=nil
      onstop()
    end
  end
end

function interp_write(cmd)
  if interp_state=='waiting' then
    trace(cmd)
    last_pos=0
    interp_obj:write(cmd)
    interp_state='running'
  else
    interp_command=cmd
  end
end

local function load_interp()
  interp_mode=interp_newmode
  if interp_mode=='prolog' then
    interp_prompt='| ?- '
  elseif interp_mode=='kotlin' then
    interp_prompt='>>> '
  else
    interp_prompt='> '
  end
  if interp_state=='stopped' then
    spawner.fulllines(false)
    interp_obj = spawner.new('"'..Utf8ToAnsi(props['SciteDefaultHome'])..'\\'..interp_mode..'.cmd"')
    interp_obj:set_output('InterpProcessChunk')
    interp_obj:set_result('InterpProcessResult')
    interp_state='loading'
    last_pos=0
    prev_chunk=''
    interp_obj:run()
  end
end

function interp_Stop()
  if interp_state=='waiting' then
    if interp_mode=='scheme' then
      interp_write('(exit)\n')
    elseif interp_mode=='hfl' then
      interp_write('quit();\n')
    elseif interp_mode=='prolog' then
      interp_write('halt(0).\n')
    elseif interp_mode=='kotlin' then
      interp_write(':quit\n')
    end
    interp_state='exiting'
    spawner.delay(1000,'kill_interp')
    last_pos=0
  elseif interp_state~='stopped' then
    kill_interp()
  elseif interp_onstop~=nil then
    local onstop=interp_onstop
    interp_onstop=nil
    onstop()
  end
end

function interp_Start(mode)
  interp_newmode=mode
  if interp_mode~= mode then
    interp_onstop=load_interp
    interp_Stop()
  elseif interp_state=='stopped' then
    load_interp()
  elseif interp_command:len()>0 then
    local cmd=interp_command
    interp_command=''
    interp_write(cmd)
  end
end

local function selection()
  local sel=props['CurrentSelection']
  if sel and sel:len()>0 then
    if sel:sub(-1)~='\n' then
      sel=sel..'\n'
    end
    return Utf8ToAnsi(sel)
  else
    return ''
  end
end

function scheme_Restart()
  interp_newmode='scheme'
  interp_onstop=load_interp
  interp_Stop()
end
function scheme_Load()
  interp_command='(load "'..Utf8ToAnsi(props['FileDir']..'\\'..props['FileNameExt']):gsub('\\','\\\\')..'")\n'
  interp_Start('scheme')
end
function scheme_Run()
  interp_command=selection()
  interp_Start('scheme')
end

function hfl_Restart()
  interp_newmode='hfl'
  interp_onstop=load_interp
  interp_Stop()
end
function hfl_Load()
  interp_command='load(\''..Utf8ToAnsi(props['FileDir']..'\\'..props['FileNameExt']):gsub('\\','\\\\')..');\n'
  interp_Start('hfl')
end
function hfl_Run()
  interp_command=selection()
  interp_Start('hfl')
end

function prolog_Restart()
  interp_newmode='prolog'
  interp_onstop=load_interp
  interp_Stop()
end
function prolog_Load()
  interp_command='consult(\''..Utf8ToAnsi(props['FileDir']..'\\'..props['FileNameExt']):gsub('\\','/')..'\').\n'
  interp_Start('prolog')
end
function prolog_Run()
  interp_command=selection()
  interp_Start('prolog')
end

function kotlin_Restart()
  interp_newmode='kotlin'
  interp_onstop=load_interp
  interp_Stop()
end
function kotlin_Load()
  interp_command=':load '..Utf8ToAnsi(props['FileDir']..'\\'..props['FileNameExt']):gsub('\\','\\\\')..'\n'
  interp_Start('kotlin')
end
function kotlin_Run()
  interp_command=selection()
  interp_Start('kotlin')
end

scite_OnOutputLine (function (line)
    if interp_state=='waiting' then
      local r=output.LineCount
      local p=output.CurrentPos
      local t=output:LineFromPosition(p)
      if t~=r-1 then
        output:DeleteRange(p-2,2)
      end
      if t==r-1 then
        line=line:sub(last_pos+1)
      elseif line:sub(1,interp_prompt:len())==interp_prompt then
        line=line:sub(interp_prompt:len()+1)
      end
      last_pos=0
      if t~=r-1 then
        trace(line..'\n')
      end
      interp_obj:write(line..'\n')
    end
end)
scite_OnClose(interp_Stop)
