/*
 * pawsborder.cpp - Author: Andrew Craig
 *
 * Copyright (C) 2003 Atomic Blue (info@planeshift.it, http://www.atomicblue.org)
 *
 *
 * 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 (version 2 of the License)
 * 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 */
// pawsborder.cpp: implementation of the pawsBorder class.
//
//////////////////////////////////////////////////////////////////////
#include <psconfig.h>

#include <ivideo/fontserv.h>

#include "pawsborder.h"
#include "pawswidget.h"
#include "pawsmanager.h"
#include "pawsprefmanager.h"

pawsBorder::pawsBorder(const char* name )
{
    usingGraphics = true;
    UseBorder( name );
    draw = true;
    titleImage = NULL;
    justTitle = false;
}

void pawsBorder::UseBorder( const char* name )
{    
    csString stylestr( name );
    // If the type is line then this is a simple border drawn using lines. 
    if ( stylestr=="line" || name == 0)
    {
        usingGraphics = false;       
    }
    else
    {
        BorderDefinition* def = PawsManager::GetSingleton().GetPrefs()->GetBorderDefinition( name );
        if ( def )
        {         
            // For each border area create the image for it based on the 
            // border definition.
            for ( int x = 0; x < PAWS_BORDER_MAX; x++ )
            {
                borderImages[x] = new pawsImage(  PawsManager::GetSingleton().GetObjectRegistry() );
                psImageDescription* desc = PawsManager::GetSingleton().GetTextureManager()->GetImageDescription( def->descriptions[x] );
                borderImages[x]->Description( desc );
            }                                           
        }            
    }
    style = BORDER_BUMP;
}


pawsBorder::~pawsBorder()
{
    delete titleImage;
}

void pawsBorder::SetParent( pawsWidget* newParent )
{
    parent = newParent;
}

csRect pawsBorder::GetRect()
{
    csRect frame = parent->ScreenFrame();

    if ( usingGraphics )
    {
        frame.xmin-=borderImages[PAWS_BORDER_TL]->GetWidth();
        frame.ymin-=borderImages[PAWS_BORDER_TL]->GetHeight();
        frame.xmax+=borderImages[PAWS_BORDER_BR]->GetWidth();
        frame.ymax+=borderImages[PAWS_BORDER_BR]->GetHeight();
    }

    if (title.Length())
    {
        int width,height;
        parent->GetFont()->GetMaxSize(width, height);
        frame.ymin -= height+6;
    }
    return frame;
}

void pawsBorder::Draw()
{
    if ( !draw )
        return;
        
    frame = parent->ScreenFrame();
    
    if (title.Length())
        DrawTitle(frame);  // This adjusts the frame to preserve the title bar if present.

    if ( !usingGraphics )
    {
        if ( !justTitle )
            DrawFrame(frame);
        return;        
    }
    
    
    /////////////////////////////
    // Draw tiles across the top
    /////////////////////////////    
    borderImages[PAWS_BORDER_TL]->Draw( frame.xmin - borderImages[PAWS_BORDER_TL]->GetWidth(), 
                                        frame.ymin - borderImages[PAWS_BORDER_TL]->GetHeight() );
                   
    int acrossTop = (int)((float)frame.Width() / 
                          (float)borderImages[PAWS_BORDER_TM]->GetWidth() + 0.5f);
                    
    int tileWidth = frame.Width() / acrossTop;    
    int locX = frame.xmin;
    int locY = frame.ymin - borderImages[PAWS_BORDER_TM]->GetHeight();
    int top = 0;    
    
    for ( top = 0; top < acrossTop-1; top++ )
    {
        borderImages[PAWS_BORDER_TM]->Draw( locX, locY, tileWidth, 0 );
        locX+=tileWidth;
    } 
    
    borderImages[PAWS_BORDER_TM]->Draw( locX, locY, 
                                        frame.Width() - tileWidth*top, 
                                        0);   
   
    borderImages[PAWS_BORDER_TR]->Draw( frame.xmax, 
                                        frame.ymin - borderImages[PAWS_BORDER_TR]->GetHeight() );
    
                                        
    /////////////////////////////
    // Draw tiles across the bottom
    /////////////////////////////    
    borderImages[PAWS_BORDER_BL]->Draw( frame.xmin - borderImages[PAWS_BORDER_BL]->GetWidth(), 
                                        frame.ymax );
                   
    int acrossBottom = (int)((float)frame.Width() / 
                          (float)borderImages[PAWS_BORDER_BM]->GetWidth() + 0.5f);
                    
    tileWidth = frame.Width() / acrossBottom;    
    locX = frame.xmin;
    locY = frame.ymax;
        
    int bottom;
    for ( bottom = 0; bottom < acrossBottom-1; bottom++ )
    {
        borderImages[PAWS_BORDER_BM]->Draw( locX, locY, tileWidth, 0 );
        locX+=tileWidth;
    } 
    
    borderImages[PAWS_BORDER_BM]->Draw( locX, locY, 
                                        frame.Width() - tileWidth*bottom, 
                                        0);   
    borderImages[PAWS_BORDER_BR]->Draw( frame.xmax, 
                                        frame.ymax);

    /////////////////////////////
    // Draw tiles down left side
    /////////////////////////////    
                   
    int downLeft = (int)((float)frame.Height() / 
                          (float)borderImages[PAWS_BORDER_LM]->GetHeight() + 0.5f);
                    
    int tileHeight = frame.Height() / downLeft;    
    locX = frame.xmin - borderImages[PAWS_BORDER_LM]->GetWidth();
    locY = frame.ymin;
        
    int left;
    for ( left = 0; left < downLeft-1; left++ )
    {
        borderImages[PAWS_BORDER_LM]->Draw( locX, locY, tileWidth, 0 );
        locY+=tileHeight;
    } 
    
    borderImages[PAWS_BORDER_LM]->Draw( locX, locY, 
                                        0,
                                        frame.Height() - tileHeight*left 
                                        );   
    
    /////////////////////////////
    // Draw tiles down left side
    /////////////////////////////    
                   
    int downRight = (int)((float)frame.Height() / 
                          (float)borderImages[PAWS_BORDER_RM]->GetHeight() + 0.5f);
                    
    tileHeight = frame.Height() / downRight;    
    locX = frame.xmax;
    locY = frame.ymin;
       
    int right; 
    for ( right = 0; right < downRight-1; right++ )
    {
        borderImages[PAWS_BORDER_RM]->Draw( locX, locY, tileWidth, 0 );
        locY+=tileHeight;
    }                                                    
    
    borderImages[PAWS_BORDER_RM]->Draw( locX, locY, 
                                        0,
                                        frame.Height() - tileHeight*right 
                                        );   
    
}

void pawsBorder::DrawTitle(csRect& frame)
{
    int width,height;
    parent->GetFont()->GetMaxSize(width, height);
    frame.ymin -= height+6;
    
    csRect r(frame);
    r.ymax = r.ymin + height+6;
    if (titleImage)
    {
            int fadeVal = parent->GetFadeVal();
            int alpha = parent->GetMaxAlpha();
            int alphaMin = parent->GetMinAlpha();
            titleImage->SetAlpha((int)(alphaMin + (alpha-alphaMin) * fadeVal * 0.010));
      titleImage->Draw(r);
    }
    if (title.Length())
    {
        int drawX=0;
        int drawY=0;
        int width=0;
        int height=0;
        
        parent->GetFont()->GetDimensions( title , width, height );  

        int midX = r.Width() / 2;
        int midY = r.Height() / 2;

        drawX = r.xmin + midX - width/2;
        drawY = r.ymin + midY - height/2;

        parent->DrawWidgetText(title,drawX,drawY, 1);
    }
}

void pawsBorder::DrawFrame(csRect frame)
{
    csRef<iGraphics2D> gfx = PawsManager::GetSingleton().GetGraphics2D();
    DrawBumpFrame( gfx, parent, frame, parent->GetBorderStyle() );
}

void DrawBumpFrame( iGraphics2D * graphics2D, pawsWidget * widget, csRect frame, int flags)
{
    int hi;
    int hi2;
    int lo;
    int lo2;
    int black;
    
//    if ( !widget->HasFocus() )
    {
        black = widget->GetBorderColour(0);

        hi    = widget->GetBorderColour(1);    
        lo    = widget->GetBorderColour(2);
    
        hi2   = widget->GetBorderColour(3);
        lo2   = widget->GetBorderColour(4);        
    }
/*    else // Temp fix to know what the highlighted widget is.
    {
        black = graphics2D->FindRGB( 0,0,0 );

        hi = graphics2D->FindRGB( 255,0,0 );
        lo = graphics2D->FindRGB( 255,0,0 );
    
        hi2 = graphics2D->FindRGB( 255,0,0 );
        lo2 = graphics2D->FindRGB( 255,0,0 );
    }*/

    if (flags & BORDER_REVERSED)
    {
        int swap;
        black = hi;
        swap = hi; hi=lo; lo=swap;
        swap = hi2; hi2=lo2; lo2=swap;
    }

    if (flags & BORDER_OUTER_BEVEL)
    {
        // Top
        graphics2D->DrawLine( frame.xmin + 0,
                            frame.ymin + 0,
                            frame.xmax - 2,
                            frame.ymin + 0,
                            hi );
        graphics2D->DrawLine( frame.xmin + 1,
                            frame.ymin + 1,
                            frame.xmax - 3,
                            frame.ymin + 1,
                            hi2 );

        // Left
        graphics2D->DrawLine( frame.xmin + 0,
                            frame.ymin + 0,
                            frame.xmin + 0,
                            frame.ymax - 2,
                            hi );

        graphics2D->DrawLine( frame.xmin + 1,
                            frame.ymin + 1,
                            frame.xmin + 1,
                            frame.ymax - 3,
                            hi2 );

        // Bottom 
        if (!(flags & BORDER_REVERSED))
        {
            graphics2D->DrawLine( frame.xmin + 1,
                                frame.ymax - 1,
                                frame.xmax - 1,
                                frame.ymax - 1,
                                black );
        }
        graphics2D->DrawLine( frame.xmin + 2,
                            frame.ymax - 2,
                            frame.xmax - 2,
                            frame.ymax - 2,
                            lo );
        // Right
        graphics2D->DrawLine( frame.xmax - 2,
                            frame.ymin + 2,
                            frame.xmax - 2,
                            frame.ymax - 2,
                            lo );

        if (!(flags & BORDER_REVERSED))
        {
            graphics2D->DrawLine( frame.xmax - 1,
                                frame.ymin + 1,
                                frame.xmax - 1,
                                frame.ymax - 1,
                                black );
        }
    }

    if (flags & BORDER_INNER_BEVEL)
    {
        // Top
        graphics2D->DrawLine( frame.xmin + 2,
                            frame.ymin + 2,
                            frame.xmax - 4,
                            frame.ymin + 2,
                            lo2 );
        graphics2D->DrawLine( frame.xmin + 3,
                            frame.ymin + 3,
                            frame.xmax - 4,
                            frame.ymin + 3,
                            black );

        // Left
        graphics2D->DrawLine( frame.xmin + 2,
                            frame.ymin + 2,
                            frame.xmin + 2,
                            frame.ymax - 4,
                            lo2 );

        graphics2D->DrawLine( frame.xmin + 3,
                            frame.ymin + 3,
                            frame.xmin + 3,
                            frame.ymax - 5,
                            black );                              

        // Bottom
        graphics2D->DrawLine( frame.xmin + 3,
                            frame.ymax - 3,
                            frame.xmax - 3,
                            frame.ymax - 3,
                            lo2 );

        graphics2D->DrawLine( frame.xmin + 4,
                            frame.ymax - 4,
                            frame.xmax - 4,
                            frame.ymax - 4,
                            hi2 );

        // Right
        graphics2D->DrawLine( frame.xmax - 3,
                            frame.ymin + 2,
                            frame.xmax - 3,
                            frame.ymax - 3,
                            lo2 );


        graphics2D->DrawLine( frame.xmax - 4,
                            frame.ymin + 3,
                            frame.xmax - 4,
                            frame.ymax - 4,
                            hi2 );
    }
}

