class GameView < NSView

    def initWithCoder(coder)
        super_initWithCoder(coder)
        
        @pixelFormat = NSOpenGLPixelFormat.alloc.initWithAttributes([
            NSOpenGLPFADoubleBuffer,
            NSOpenGLPFADepthSize, 16, # CBA making an FBO for a prototype...
            NSOpenGLPFAAllowOfflineRenderers,
            0
        ])
        @context = NSOpenGLContext.alloc.initWithFormat_shareContext(
            @pixelFormat, nil)
        
        @context.setValues_forParameter([1], NSOpenGLCPSwapInterval)
        
        NSTimer.scheduledTimerWithTimeInterval_target_selector_userInfo_repeats(
            0.001, self, 'drawGL', nil, true)
        
        self.setPostsFrameChangedNotifications(true)
        NSNotificationCenter.defaultCenter.addObserver_selector_name_object(
            self,
            'frameChanged',
            NSViewFrameDidChangeNotification,
            self)
        
        @first_frame = true
        
        self
    end
    
    def drawRect(rect)
        drawGL
    end
    
    def frameChanged(note)
        box = bounds
        
        if @trackingRectTag then
            removeTrackingRect(@trackingRectTag)
        end
        addTrackingRect_owner_userData_assumeInside(box, self, nil, false)
        
        @context.update
    
        $game.opengl_context_resized(bounds.width, bounds.height)
    end
    
    def drawGL
        if @first_frame
            if ENV['FOREGROUND'] then
                NSApplication.sharedApplication.activateIgnoringOtherApps(true)
            end
            
            Dir.chdir(NSBundle.mainBundle.resourcePath)
            
            @context.setView(self)
            @context.makeCurrentContext()
            
            window.setAcceptsMouseMovedEvents(true)
            
            $game.opengl_context_created()
            frameChanged(nil)
            
            @last_frame_time = NSDate.timeIntervalSinceReferenceDate
            @first_frame = false
        end
        
        # TODO use mach_absolute_time (or CA/CV proxy to it)
        now = NSDate.timeIntervalSinceReferenceDate
        dt = now - @last_frame_time
        @last_frame_time = now
        
        $game.display(dt)
        
        if ENV['DEBUG'] then
            err = glGetError()
            $stderr.puts gluErrorString(err) unless err = GL_NO_ERROR
        end
        
        @context.flushBuffer()
    end
    
    def applicationShouldTerminateAfterLastWindowClosed(sender)
        true
    end
    
    ib_action :toggleFullScreen do |sender|
        if isInFullScreenMode then
            exitFullScreenModeWithOptions(nil)
            # why is this necessary?!
            window.makeFirstResponder(self)
        else
            enterFullScreenMode_withOptions(window.screen, nil)
        end
    end
    
    def keyDown(event)
        NSCursor.setHiddenUntilMouseMoves(true)
        $game.key_pressed(event.keyCode)
        $game.text_entered(event.characters)
    end
    
    def keyUp(event)
        $game.key_released(event.keyCode)
    end
    
    def mouseDown(event)
        _mouse_pressed(event)
    end
    
    def rightMouseDown(event)
        _mouse_pressed(event)
    end
    
    def otherMouseDown(event)
        _mouse_pressed(event)
    end
    
    def _mouse_pressed(event)
        $game.mouse_pressed(event.buttonNumber)
    end
    
    def mouseUp(event)
        _mouse_released(event)
    end
    
    def rightMouseUp(event)
        _mouse_released(event)
    end
    
    def otherMouseUp(event)
        _mouse_released(event)
    end
    
    def _mouse_released(event)
        $game.mouse_released(event.buttonNumber)
    end
    
    def mouseDragged(event)
        _mouse_moved(event)
    end
    
    def rightMouseDragged(event)
        _mouse_moved(event)
    end
    
    def otherMouseDragged(event)
        _mouse_moved(event)
    end
    
    def mouseMoved(event)
        _mouse_moved(event)
    end
    
    def _mouse_moved(event)
        $game.mouse_moved_by(event.deltaX, event.deltaY)
        where = event.locationInWindow
        $game.mouse_moved_to(where.x, where.y)
    end
    
    def mouseEntered(event)
        #NSCursor.hide()
    end
    
    def mouseExited(event)
        #NSCursor.unhide()
    end
    
    def acceptsFirstResponder
        true
    end

end
