#include "basis.h"

static void Init(void );
static void CALLBACK Reshape(int width,int height);
static void CALLBACK Draw(void );
static void CALLBACK Key_0(void );
static void CALLBACK Key_1(void );
static void CALLBACK Key_2(void );
static void CALLBACK Key_3(void );
static void CALLBACK Key_4(void );
static void CALLBACK Key_5(void );
static void CALLBACK Key_6(void );
static void CALLBACK Key_7(void );
static void CALLBACK Key_8(void );
static void CALLBACK Key_9(void );

GLint  windW, windH;
GLenum typePrim;
GLint blendSrc, blendDst, alphaFunc;

static void Init(void)
{
  glClearColor(1.0f, 1.0f, 1.0f, 1.0f);

  typePrim  = GL_FALSE;
  blendSrc = GL_SRC_ALPHA;
  blendDst = GL_ONE_MINUS_SRC_ALPHA;
  alphaFunc = GL_LESS;
}

static void CALLBACK Reshape(int width, int height)
{
  windW = (GLint)width;
  windH = (GLint)height;
}

static void CALLBACK Key_0(void)
{
  if(alphaFunc == GL_LESS)
    alphaFunc = GL_GREATER;
  else
    alphaFunc = GL_LESS;
}

static void CALLBACK Key_1(void)
{
  blendSrc = GL_SRC_ALPHA;
  blendDst = GL_ONE_MINUS_SRC_ALPHA;
}

static void CALLBACK Key_2(void)
{
  blendSrc = GL_DST_ALPHA;
  blendDst = GL_ONE_MINUS_DST_ALPHA;
}

static void CALLBACK Key_3(void)
{
  blendSrc = GL_SRC_ALPHA;
  blendDst = GL_ONE_MINUS_DST_ALPHA;
}

static void CALLBACK Key_4(void)
{
  blendSrc = GL_DST_ALPHA;
  blendDst = GL_ONE_MINUS_SRC_ALPHA;
}

static void CALLBACK Key_5(void)
{
  blendSrc = GL_SRC_ALPHA_SATURATE;
  blendDst = GL_ONE_MINUS_SRC_ALPHA;
}

static void CALLBACK Key_6(void)
{
  blendSrc = GL_SRC_ALPHA_SATURATE;
  blendDst = GL_SRC_COLOR;
}

static void CALLBACK Key_7(void)
{
  blendSrc = GL_SRC_ALPHA_SATURATE;
  blendDst = GL_ONE;
}

static void CALLBACK Key_8(void)
{
  blendSrc = GL_SRC_ALPHA_SATURATE;
  blendDst = GL_SRC_ALPHA;
}

static void CALLBACK Key_9(void)
{
  blendSrc = GL_SRC_ALPHA;
  blendDst = GL_DST_ALPHA;
}

static void CALLBACK DrawBorder(int left)
{
  GLint x;
  GLushort pattern;
  GLfloat width;

  if(!left){
    pattern = 0x1C47;
    x = windW/4;
  }
  else{
    pattern = 0x471C;
    x = -windW/4;
  }
  glPushMatrix();
    glGetFloatv(GL_LINE_WIDTH, &width);
    glLineWidth(2.0f);
    glLineStipple(2, pattern);
    glEnable(GL_LINE_STIPPLE);
    glBegin(GL_LINES);
      glColor3f(0.0f, 0.0f, 0.0f);
      glVertex2i(x, -windH/2);
      glColor3f(0.0f, 0.0f, 0.0f);
      glVertex2i(x,  windH/2);
    glEnd();
    glDisable(GL_LINE_STIPPLE);
    glLineWidth(width);
  glPopMatrix();
}

static void CALLBACK InitViewport(int x, int y, int width, int height)
{
  glViewport(x, y, width, height);

  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  gluOrtho2D(-windW/4, windW/4, -windH/2, windH/2);
  glMatrixMode(GL_MODELVIEW);
}

static void CALLBACK DrawScene(GLint mode)
{
  // Здесь вызываются команды рисования
  // ...

  glColor4f(1.0f, 0.0f, 0.0f, 0.75f);
  glRecti(-windW/4 + 20, -windH/2 + 20,
           windW/4 - 20,  20);

  if(mode){
    glEnable(GL_BLEND);
    glEnable(GL_ALPHA_TEST);
  }

  glColor4f(0.0f, 0.0f, 1.0f, 0.25f);
  glRecti( 20, -windH/2 + 20,
           windW/4 - 10, windH/2 - 20);
  
  glDisable(GL_ALPHA_TEST);
    
  glColor4f(0.0f, 0.0f, 1.0f, 0.75f);
  glRecti(-windW/4 + 10, -windH/2 + 20,
          - 20, windH/2 - 20);
  glDisable(GL_BLEND);
}

static void CALLBACK Draw(void)
{
  glClear(GL_COLOR_BUFFER_BIT);
  glBlendFunc(blendSrc, blendDst);
  glAlphaFunc(alphaFunc, 0.5f);
    
  InitViewport(0,0, windW/2, windH);
  DrawBorder(0);

  glColor3f(0.0, 0.0, 1.0);
  DrawScene(0);

  InitViewport(windW/2, 0, windW/2, windH);
  DrawBorder(1);
  
  glColor3f(1.0, 0.0, 0.0);
  DrawScene(1);

  glFinish();
  auxSwapBuffers();
}

void main(int argc, char **argv)
{
    windW = 400;
    windH = 300;
    auxInitPosition(200, 100, windW, windH);

    auxInitDisplayMode(AUX_RGB | AUX_DOUBLE);

    if (auxInitWindow("Альфа тестирование") == GL_FALSE) {
      auxQuit();
    }

    Init();

    auxExposeFunc((AUXEXPOSEPROC)Reshape);
    auxReshapeFunc((AUXRESHAPEPROC)Reshape);
    auxKeyFunc(AUX_0, Key_0);
    auxKeyFunc(AUX_1, Key_1);
    auxKeyFunc(AUX_2, Key_2);
    auxKeyFunc(AUX_3, Key_3);
    auxKeyFunc(AUX_4, Key_4);
    auxKeyFunc(AUX_5, Key_5);
    auxKeyFunc(AUX_6, Key_6);
    auxKeyFunc(AUX_7, Key_7);
    auxKeyFunc(AUX_8, Key_8);
    auxKeyFunc(AUX_9, Key_9);
    auxMainLoop(Draw);
}
