--------------------------------------------------------------------------------
-- ASOTP "IGLA" black indicator unit for 81-720
--------------------------------------------------------------------------------
-- Copyright (C) 2013-2018 Metrostroi Team & FoxWorks Aerospace s.r.o.
-- Contains proprietary code. See license.txt for additional information.
--------------------------------------------------------------------------------
Metrostroi.DefineSystem("81_720_IGLA_CBKI2")
TRAIN_SYSTEM.DontAccelerateSimulation = true

function TRAIN_SYSTEM:Initialize()
    self.State = -2
    self.Log = {}
    self.States = {}
    self.Messages = {}
    self.MessagesCount = 0
    self.Train:LoadSystem("IGLA1U","Relay","Switch",{bass = true})
    self.Train:LoadSystem("IGLA1","Relay","Switch",{bass = true})
    self.Train:LoadSystem("IGLA1D","Relay","Switch",{bass = true})
    self.Train:LoadSystem("IGLA2U","Relay","Switch",{bass = true})
    self.Train:LoadSystem("IGLA2","Relay","Switch",{bass = true})
    self.Train:LoadSystem("IGLA2D","Relay","Switch",{bass = true})


    self.TriggerNames = {
        "IGLA1U",
        "IGLA1",
        "IGLA1D",
        "IGLA2U",
        "IGLA2",
        "IGLA2D",
    }
    self.Triggers = {}
end
if TURBOSTROI then return end
function TRAIN_SYSTEM:Inputs()
    return {  "" }
end
if CLIENT then
    local function FormatEnd1(num)
        if num == 1 then return " "
        elseif 1 < num and num < 5 then return "а" end
        return "ов"
    end
    local function FormatEnd2(num)
        if num == 1 then return "ка"
        elseif 1 < num and num < 5 then return "ки" end
        return "ок"
    end
    surface.CreateFont("Metrostroi_ILGAo", {
        font = "Liquid Crystal Display",
        size = 40,
        weight = 800,
        blursize = false,
        antialias = true,
        underline = false,
        italic = false,
        strikeout = false,
        symbol = false,
        rotary = false,
        shadow = false,
        additive = false,
        outline = false,
        extended = true,
        scanlines = false,
    })
  function TRAIN_SYSTEM:PrintText(x,text,inverse)
    local str = {utf8.codepoint(text,1,-1)}
    for i=1,#str do
        local char = utf8.char(str[i])
      if inverse then
        draw.SimpleText(string.char(0x7f),"Metrostroi_ILGAo",(x+i)*30,42,Color(0,0,0),TEXT_ALIGN_CENTER,TEXT_ALIGN_CENTER)
        draw.SimpleText(char,"Metrostroi_ILGAo",(x+i)*30,42,Color(140,190,0,150),TEXT_ALIGN_CENTER,TEXT_ALIGN_CENTER)
      else
        draw.SimpleText(char,"Metrostroi_ILGAo",(x+i)*30,42,Color(0,0,0,255),TEXT_ALIGN_CENTER,TEXT_ALIGN_CENTER)
      end
    end
  end
  function TRAIN_SYSTEM:ClientThink()
    if not self.Train:ShouldDrawPanel("IGLA") then return end
    --RunConsoleCommand("say","президент!!!")
    if not self.DrawTimer then
        render.PushRenderTarget(self.Train.IGLA,0,0,512, 128)
        render.Clear(0, 0, 0, 0)
        render.PopRenderTarget()
    if self.DrawTimer and CurTime()-self.DrawTimer < 0.1 then return end
    end
    self.DrawTimer = CurTime()
    render.PushRenderTarget(self.Train.IGLA,0,0,512, 128)
    --render.Clear(0, 0, 0, 0)
    cam.Start2D()
        self:IGLA(self.Train)
    cam.End2D()
    render.PopRenderTarget()
  end

    local messages = {
        START = "пит цбки вкл",
        CONN = "подкл",
        DISCONN = "пот связ",
        SCHEME = "несб сх",
        BV = "сраб бв",
        DOORS = "откр дв",
        BBE = "выкл ббэ",
        PARKING = "вкл ст т",
        BRAKES = "вкл пн т",
        UAVA = "сраб СК",
        UAVAK = "кон уава",
        EPK = "сраб эпв",
        ARS = "прев арс",
        RU = "вкл рвр",
    }
    function TRAIN_SYSTEM:IGLA()
        local Train = self.Train
        local State = self.Train:GetNW2Int("IGLA:State",0)
        if State > -2 then
            surface.SetDrawColor(81,223,0,self.Warm and 100 or 255)
            surface.DrawRect(0,0,512,80)
            self.Warm = true
        else
            surface.SetDrawColor(81*0.2,223*0.2,0,230)
            surface.DrawRect(0,0,512,80)
            self.Warm = false
        end

        if State == 0 then
            self:PrintText(0,"Chip test Ok Ok")
        elseif State == 1 then
            self:PrintText(0,"АСОТП-\"ИГЛА\" V02")
        elseif State == 2 then
            local State2 = Train:GetNW2Int("IGLA:State2",0)
            if State ~= self.OldState then
                self.Timer = RealTime()
                self.OldState = State
            end
            if State2 == 0 then
                --self:PrintText(0,"")
                self:PrintText(0,Format("[%03d]",Train:GetNW2Int("IGLA:Messages")))
                self:PrintText(7,"ПЦБК-"..Train:GetNW2Int("IGLA:Count",0))
            elseif State2 == 1 then
                local w = Train:GetNW2Int("IGLA:WagNumber")
                local m = Train:GetNW2String("IGLA:LogID")
                local s = Train:GetNW2Int("IGLA:Selected")
                if s ~= self.OldSel then
                    self.Timer = RealTime()-0.01
                    self.OldSel = s
                end
                if messages[m] then m = messages[m] end
                local timer = math.ceil((RealTime()-self.Timer)%3)
                if w > 0 then self:PrintText(0,Format("[%05d]",w)) else self:PrintText(0,"[]") end
                if timer == 1 then
                    if w > 0 then
                        self:PrintText(7,m)
                    else
                        self:PrintText(2,m)
                    end
                elseif timer == 2 then
                    local d = Train:GetNW2Int("IGLA:LogDate")
                    self:PrintText(w > 0 and 7 or 2,os.date("!%H:%M:%S",d))
                else
                    local d = Train:GetNW2Int("IGLA:LogDate")
                    self:PrintText(w > 0 and 7 or 2,os.date("!%d-%m-%y",d))
                end
                if Train:GetNW2Int("IGLA:Arrow") == -1 then
                    self:PrintText(15,"<")
                elseif Train:GetNW2Int("IGLA:Arrow") == 1 then
                    self:PrintText(15,">")
                else
                    self:PrintText(15,"<")
                    self:PrintText(15,">")
                end
            elseif State2 == 2 then
                local w = Train:GetNW2Int("IGLA:WagNumber")
                local m = Train:GetNW2String("IGLA:ErrorID")
                local s = Train:GetNW2Int("IGLA:Selected")
                if s ~= self.OldSel then
                    self.Timer = RealTime()-0.01
                    self.OldSel = s
                end
                if messages[m] then m = messages[m] end
                local timer = math.ceil((RealTime()-self.Timer)%3)
                if w > 0 then self:PrintText(0,Format("[%05d]",w)) else self:PrintText(0,"[]") end
                if timer == 1 then
                    if w > 0 then
                        self:PrintText(7,m)
                    else
                        self:PrintText(2,m)
                    end
                elseif timer == 2 then
                    local d = Train:GetNW2Int("IGLA:LogDate")
                    self:PrintText(w > 0 and 7 or 2,os.date("!%H:%M:%S",d))
                else
                    local d = Train:GetNW2Int("IGLA:LogDate")
                    self:PrintText(w > 0 and 7 or 2,os.date("!%d-%m-%y",d))
                end
                if Train:GetNW2Int("IGLA:Arrow") == -1 then
                    self:PrintText(15,"<")
                elseif Train:GetNW2Int("IGLA:Arrow") == 1 then
                    self:PrintText(15,">")
                else
                    self:PrintText(15,"<")
                    self:PrintText(15,">")
                end
            end
        end
    end
else
    function TRAIN_SYSTEM:CANReceive(source,sourceid,target,targetid,textdata,numdata)
        if self.State < 2 then return end
        if not self.States[sourceid] then
            self.States[sourceid] = {}
            table.insert(self.Log,{"CONN",sourceid,Metrostroi.GetSyncTime()})
        end
        self.States[sourceid][textdata] = numdata
    end
    function TRAIN_SYSTEM:CANWrite(name,value)
        self.Train:CANWrite("IGLA_CBKI",self.Train:GetWagonNumber(),"IGLA_PCBK",nil,name,value)
    end
    function TRAIN_SYSTEM:Trigger(name,value)
        if self.State == 2 then
            if self.State2 == 0 then
                if name == "IGLA2D"  and value and #self.Log > 0 then
                    self.State2 = 1
                    self.StandbyTimer = CurTime()
                    self.Selected = #self.Log
                end
                if name == "IGLA1D"  and value and #self.Messages > 0 then
                    self.State2 = 2
                    self.StandbyTimer = CurTime()
                    self.Selected = #self.Messages
                end
            elseif self.State2 == 1 then
                self.StandbyTimer = CurTime()
                if name == "IGLA2D"  and value and self.Selected > 1 then
                    self.Selected = self.Selected - 1
                end
                if name == "IGLA2"  and value then
                    self.State2 = 0
                end
                if name == "IGLA2U"  and value and self.Selected < #self.Log then
                    self.Selected = self.Selected + 1
                end
            elseif self.State2 == 2 then
                self.StandbyTimer = CurTime()
                if name == "IGLA1D"  and value and self.Selected > 1 then
                    self.Selected = self.Selected - 1
                end
                if name == "IGLA1"  and value then
                    self.State2 = 0
                end
                if name == "IGLA1U"  and value and self.Selected < #self.Messages then
                    self.Selected = self.Selected + 1
                end
            end
        end
    end
    local Logging = {
        SCHEME = false,
        BV = true,
        DOORS = true,
        BBE = true,
        PARKING = true,
        BRAKES = true,
        UAVA = true,
        ARS = true,
        RU = true,
    }
    function TRAIN_SYSTEM:CError(WagID,ErrID,status)
        local ID = WagID..ErrID
        if not self.Messages[ID] and status then
            self.Messages[ID] = table.insert(self.Messages,{ErrID,WagID,Metrostroi.GetSyncTime(),ID})
            if Logging[ErrID] then
                table.insert(self.Log,self.Messages[self.Messages[ID]])
            end
            --print(Format("Message with ErrID '%s' have ID:%d",ID,self.Messages[ID]))
        elseif self.Messages[ID] and not status then
            --print(Format("Removed message with ErrID '%s' have ID:%d",ID,self.Messages[ID]))
            table.remove(self.Messages,self.Messages[ID])
            self.Messages[ID] = nil
            for k,v in ipairs(self.Messages) do
                self.Messages[v[4]] = k
            end
        end
    end
    function TRAIN_SYSTEM:Think(dT)
        local Train = self.Train
        local power = Train.Panel.CBKIPower > 0
        if power and self.State ~= -2  then
            for k,v in pairs(self.TriggerNames) do
                if Train[v] and (Train[v].Value > 0.5) ~= self.Triggers[v] then
                    self:Trigger(v,Train[v].Value > 0.5)
                    self.Triggers[v] = Train[v].Value > 0.5
                end
            end
        end
        if not power or self.Reset then
            self.Reset = false
            if self.State ~= -2 then
                self.State = -2
                self.Timer = nil
                self.Fire = false
                self.Error = false
                self.PCBKCount = 0
                self.States = {}
                self.Messages = {}
            end
        end
        if self.State == -2 and power then
            self.State = -1
            self.Timer = CurTime()+math.random()*0.3
            self.StartError = false
        end
        if self.State == -1 and CurTime()-self.Timer > 0.3 then
            self.State = 0
            Train:PlayOnce("igla_start1","cabin")
            self.Timer = CurTime()+math.random()*0.6
        end
        if self.State == 0 and CurTime()-self.Timer > 3.4 then
            table.insert(self.Log,{"START",sourceid,Metrostroi.GetSyncTime()})
            self.State = 1
            Train:PlayOnce("igla_start2","cabin")
            self.Timer = CurTime()+math.random()*0.4
        end
        if self.State == 1 then
            self.Fire = true
            self.Error = true
            if CurTime()-self.Timer > 4 then
                self.State = 2
                self.State2 = 0
                self.StandbyTimer = CurTime()
                self.ShowTimeTimer = nil
                self.ShowTime = false

                self.PCBKTimer = nil
            end
        elseif self.State == 2 then
            local Standby = CurTime()-self.StandbyTimer > 10
            if self.State2 > 0 and Standby then self.State2 = 0 end
            if self.ShowTimeTimer and self.ShowTimeTimer ~= true and CurTime()-self.ShowTimeTimer > 1.5 then
                self.ShowTime = not self.ShowTime
                self.ShowTimeTimer = true
            end
            if not self.PCBKTimer or CurTime()-self.PCBKTimer > 1.4 then
                self:CANWrite("Update",1)
                self.PCBKTimer = CurTime()+math.random()*0.4
            end

            local count = 0
            for k,v in pairs(self.States) do
                local timer = CurTime()-v.Timer
                if timer <= 5 then
                    for id in pairs(Logging) do self:CError(k,id,v[id]) end
                    count = count + 1
                else
                    for k1,v1 in ipairs(self.Messages) do
                        if v1[2] == k then
                            --print(Format("Removed message with ErrID '%s' have ID:%d, PCBK discon",v1[4],self.Messages[v1[4]]))
                            self.Messages[v1[4]] = nil
                            table.remove(self.Messages,k1)
                        end
                    end
                    table.insert(self.Log,{"DISCONN",k,Metrostroi.GetSyncTime()})
                    self.States[k] = nil
                end
            end
            self.PCBKCount = count
            if self.MessagesCount ~= #self.Messages then
                local mess = #self.Messages
                if self.MessagesCount < mess then
                    Train:PlayOnce("igla_start2","cabin",nil,1)
                    self.StandbyTimer = CurTime()
                    if self.State2 ~= 2 then
                        self.State2 = 2
                        self.Selected = mess
                    end
                    if self.Selected >= self.MessagesCount then
                        self.Selected = mess
                    end
                end
                if self.State2 == 2 and self.Selected > mess then self.Selected = mess end
                if self.State2 == 2 and mess == 0 then
                    self.State2 = 0
                end
                self.MessagesCount = mess
            end

            if self.State2 == 0 then
                self.Fire = false
                self.Error = self.MessagesCount > 0
            elseif self.State2 == 1 then
                local log = self.Log[self.Selected]
                Train:SetNW2Int("IGLA:Selected",self.Selected)
                Train:SetNW2String("IGLA:LogID",log[1])
                Train:SetNW2Int("IGLA:WagNumber",log[2])
                Train:SetNW2Int("IGLA:LogDate",log[3])
                for i=4,#log do
                    Train:SetNW2Int("IGLA:Log"..i,log[i])
                end
                if CurTime()-self.StandbyTimer > 10 then self.State2 = 0 end
                Train:SetNW2Int("IGLA:Arrow",self.Selected == 1 and 1 or self.Selected == #self.Log and -1 or 0)
                self.Error = false
            elseif self.State2 == 2 then
                local err = self.Messages[self.Selected]
                Train:SetNW2Int("IGLA:Selected",self.Selected)
                Train:SetNW2String("IGLA:ErrorID",err[1])
                Train:SetNW2Int("IGLA:WagNumber",err[2])
                Train:SetNW2Int("IGLA:Arrow",self.Selected == 1 and 1 or self.Selected == #self.Messages and -1 or 0)

                if CurTime()-self.StandbyTimer > 10 then self.State2 = 0 end
                self.Fire = false
            end
        end
        self.Error = self.MessagesCount > 0
        Train:SetNW2Int("IGLA:Count",self.PCBKCount)
        Train:SetNW2Int("IGLA:State2",self.State2)
        Train:SetNW2Bool("IGLA:Messages",#self.Log)
        Train:SetNW2Bool("IGLASR",self.State > -2)
        Train:SetNW2Bool("IGLARX",self.State > -2 and self.PCBKCount == 0)
        Train:SetNW2Bool("IGLAErr",self.State > 0 and self.Error or self.State == 1)
        Train:SetNW2Bool("IGLAOSP", self.State == 1)
        Train:SetNW2Bool("IGLAPI", self.State == 1)
        Train:SetNW2Bool("IGLAOff", self.State == 1)


        Train:SetNW2Int("IGLA:State",self.State)
    end
end
