//
// Applesoft BASIC Interpreter in Javascript
// High Resolution Graphics (HiRes) Emulation
//

// Copyright 2009 Joshua Bell
// 
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// 
// http://www.apache.org/licenses/LICENSE-2.0
// 
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.


// Usage:
//   
//   var hires = new LoRes( element, width, height )
//   hires.clear()
//   hires.setColor( color_index )
//   hires.plot( x, y )
//   hires.plot_to( x, x )
//   hires.show( bool )
//   { width: w, height: h } = hires.getScreenSize()
//   
// Example:
//
//   <script>
//     hires = new HiRes( document.getElementById( 'hires' ), 140, 192 );
//     interpreter = new BasicInterpreter( tty, lores, hires, paddle );
//   </script>
//   <canvas id="hires"></canvas>

/*extern document */

function HiRes( element, columns, rows )
{
    // For references to "this" within callbacks and closures
    var self = this;
    
    self.screenElement = element;
    self.screenWidth = columns;
    self.screenHeight = rows;
    
    // Colors c/o USENET:
    // Date: Wed, 05 Sep 2007 01:04:20 +0200
    // From: Linards Ticmanis <ticmanis@gmx.de>
    // Newsgroups: comp.sys.apple2
    // Subject: Re: Double hires mode color artifacts
    // Message-ID: <46dde477$0$4527$9b4e6d93@newsspool3.arcor-online.net>

    var colors = [ 
        '#000000', // Black 1
        '#2fbc1a', // Green
        '#d043e5', // Violet
        '#ffffff', // White 1
        '#000000', // Black 2
        '#d06a1a', // Orange 
        '#2f95e5', // Medium Blue 
        '#ffffff'  // White 2
        ];

    self.color = 0;
    
    self.last_x = 0;
    self.last_y = 0;

    //----------------------------------------------------------------------
    function init()
    //----------------------------------------------------------------------
    {
        self.screenElement.setAttribute( "width",  self.screenWidth  );
        self.screenElement.setAttribute( "height", self.screenHeight );
        
        self.context = self.screenElement.getContext( "2d" );

    } // init
    
    
    //----------------------------------------------------------------------
    this.clear = function()
    //----------------------------------------------------------------------
    {
        self.context.clearRect( 0, 0, self.screenWidth, self.screenHeight );
        
    }; // clear

    //----------------------------------------------------------------------
    this.setColor = function( color )
    //----------------------------------------------------------------------
    {
        self.color = Math.floor( color ) % colors.length;
    }; // setColor

    //----------------------------------------------------------------------
    this.plot = function( x, y )
    //----------------------------------------------------------------------
    {
        self.last_x = x;
        self.last_y = y;

        self.context.strokeStyle = colors[ self.color ];
        self.context.beginPath();
        self.context.moveTo( x/2, y );
        self.context.lineTo( (x+1)/2, y );
        self.context.stroke();

    }; // plot

    //----------------------------------------------------------------------
    this.plot_to = function( x, y )
    //----------------------------------------------------------------------
    {
        self.context.strokeStyle = colors[ self.color ];
        self.context.beginPath();
        self.context.moveTo( self.last_x/2, self.last_y );
        self.context.lineTo( x/2, y ); // TODO: Replace with own Brezenham to avoid aliasing
        self.context.stroke();

        self.last_x = x;
        self.last_y = y;        

    }; // plot_to
    
    //----------------------------------------------------------------------
    this.getScreenSize = function()
    //----------------------------------------------------------------------
    {
        return { width: self.screenWidth, height: self.screenHeight };
    }; // getScreenSize
    

    //----------------------------------------------------------------------
    this.show = function( state )
    //----------------------------------------------------------------------
    {
        self.screenElement.style.visibility = state ? "visible" : "hidden";
        
    }; // show

    //----------------------------------------------------------------------
    // Constructor Logic
    //----------------------------------------------------------------------
        
    init();
}
