=begin
Timba language interpreter.
Copyright (C) 2016  Nicolas Guzzo

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
=end	
require './highlighter.rb'

class LineNumberArea < Qt::Widget
	def initialize(parent = nil,te)
	    super(parent)
	    @texteditor=te
	    setSizePolicy(Qt::SizePolicy::Fixed, Qt::SizePolicy::Expanding)
	end
	def minimumSizeHint()
	    return Qt::Size.new(40, 100)
	end	
	def sizeHint()
	    return Qt::Size.new(40, 100)
	end
	def paintEvent(event)
    	painter = Qt::Painter.new(self)
	    painter.fillRect(event.rect, Qt::lightGray)
	    block =  @texteditor.firstVisibleBlock()
	    blockNumber = block.blockNumber()
	    top = @texteditor.blockBoundingGeometry(block).translated( @texteditor.contentOffset()).top()
	    bottom = top +  @texteditor.blockBoundingRect(block).height()
	    while (block.isValid() and top <= event.rect.bottom())
	        if (block.isVisible() and bottom >= event.rect.top()) 
	            number = (blockNumber + 1).to_s	            
	            painter.setPen(Qt::black)
	            painter.drawText(0, top+1, width(), fontMetrics().height(),
	                             Qt::AlignRight, number)
	        end
	        block = block.next()
	        top = bottom
	        bottom = top +  @texteditor.blockBoundingRect(block).height()
	        blockNumber+=1
	    end
	    painter.end
	end
end

class Editor < Qt::Widget
	slots 'on_change()','updateLineNumberArea(QRect,int)'
	def initialize(parent = nil,statusbar)
	    super(parent)	    
	    @fileName=nil
	    @statusbar=statusbar
	    @textedit=Qt::PlainTextEdit.new()
	    @linearea=LineNumberArea.new(nil,@textedit)

	    @highlighter = Highlighter.new	    
	    setupEditor()
	    @sel_color = Qt::Brush.new(Qt::Color.new(Qt::yellow).lighter(160));
	    @error_color = Qt::Brush.new(Qt::Color.new(Qt::red));

	    connect(@textedit, SIGNAL('cursorPositionChanged()'), self, SLOT('on_change()'))
	    connect(@textedit, SIGNAL('updateRequest(QRect,int)'), self, SLOT('updateLineNumberArea(QRect,int)'));
	    self.layout = Qt::HBoxLayout.new do |m|
            m.addWidget(@linearea)
            m.addWidget(@textedit)
        end
        self.layout.setMargin(0)
        self.layout.setSpacing(0)	    
	end
	def get_text()
		@textedit.document.toPlainText
	end
	def updateLineNumberArea(rect,dy)	
	    @linearea.update
	end
	def on_change()
		line=1
		col=1
		line=@textedit.textCursor().blockNumber()+1
		col=@textedit.textCursor().positionInBlock()+1
		@statusbar.showMessage(tr("linea #{line}, columna #{col}"))		    
		sel_line()
	end
	def go_to(l)
		text_block = @textedit.document().findBlockByLineNumber(l-1) 
		text_cursor = @textedit.textCursor()
		text_cursor.setPosition (text_block.position())	
		#central_widget_TextEdit->setFocus();
		@textedit.setTextCursor(text_cursor)
	end
	def mark_errors(errorlist)
		extraSelections=[]
	        
	    errorlist.each do |err|
	    	go_to(err)
		    selection= Qt::TextEdit::ExtraSelection.new
		    selection.format.setBackground(@error_color)		   
		    selection.format.setProperty(Qt::TextFormat::FullWidthSelection, Qt::Variant.new(true))
		    selection.cursor = @textedit.textCursor();
		    selection.cursor.clearSelection();
		    extraSelections<<selection;
		end	    
	    @textedit.setExtraSelections(extraSelections);
	end
	def sel_line(err=false)
		extraSelections=[]	        
	    selection= Qt::TextEdit::ExtraSelection.new
	    selection.format.setBackground(@sel_color)
	    selection.format.setProperty(Qt::TextFormat::FullWidthSelection, Qt::Variant.new(true))
	    selection.cursor = @textedit.textCursor();
	    selection.cursor.clearSelection();
	    extraSelections<<selection;	    
	    @textedit.setExtraSelections(extraSelections);
	end
	def newFile()
		@fileName =nil
	    @textedit.clear()
	end
	def save(fn)
		file = Qt::File.new(fn)
		if file.open(Qt::File::WriteOnly | Qt::File::Text)
			file.write(@textedit.plainText)
		end
		file.close
	end
	def saveFile()
		if @fileName !=nil and @fileName !=""
			save(@fileName)
		else
			@fileName = Qt::FileDialog.getSaveFileName(@textedit,tr("Guardar Archivo"), "", "Timba Files (*.tba)")			
			save(@fileName) if @fileName !=nil and @fileName !=""
		end
	end
	def openFile(path = nil)
	    @fileName = path
	
	    if @fileName.nil?
	        @fileName = Qt::FileDialog.getOpenFileName(self,
	            tr("Abrir Archivo"), "", "Timba Files (*.tba)")
		end
	
	    if !@fileName.nil?
	        file = Qt::File.new(@fileName)
	        if file.open(Qt::File::ReadOnly | Qt::File::Text)
	            @textedit.plainText = file.readAll.to_s
			end
			file.close
	    end
	    @highlighter.highlight_all(@textedit.document)
	end
	
	def setupEditor()
	    variableFormat = Qt::TextCharFormat.new
	    variableFormat.fontWeight = Qt::Font::Bold
	    variableFormat.foreground = Qt::Brush.new(Qt::blue)
	    @highlighter.addMapping('pila\s*[A-Z_]+', variableFormat)

	    
	    singleLineCommentFormat = Qt::TextCharFormat.new
	    singleLineCommentFormat.background = Qt::Brush.new(Qt::Color.new("#77ff77"))
	    @highlighter.addMapping('#[^\n]*', singleLineCommentFormat)
	
	    controlFormat = Qt::TextCharFormat.new	    
	    controlFormat.foreground = Qt::Brush.new(Qt::blue)
	    @highlighter.addMapping(/(sino|si\s+|mientras|nada\s+mas|repita)/i, controlFormat)

	    opFormat = Qt::TextCharFormat.new	    
	    opFormat.foreground = Qt::Brush.new(Qt::Color.new("#008000"))
	    @highlighter.addMapping(/(invierta(la)?|deposite(la)?|tome|(la\s+)?carta\s+)/i, opFormat)
		
		defFormat = Qt::TextCharFormat.new
	    defFormat.fontWeight = Qt::Font::Bold
	    defFormat.background = Qt::Brush.new(Qt::cyan)
	    defFormat.foreground = Qt::Brush.new(Qt::black)
	    @highlighter.addMapping(/(definicion\s+de\s+programa|ucp\s+ejecute\s+con\s+las\s+siguientes\s+cartas)/i, defFormat)
	    
	    font = Qt::Font.new
	    font.family = "Courier"
	    font.fixedPitch = true
	    font.pointSize = 12
	
	    font = font
	    @highlighter.addToDocument(@textedit.document())
	end
end