/*
** Copyright (c) 2006,2007 D. Richard Hipp
**
** This program is free software; you can redistribute it and/or
** modify it under the terms of the GNU General Public
** License version 2 as published by the Free Software Foundation.
**
** 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 library; if not, write to the
** Free Software Foundation, Inc., 59 Temple Place - Suite 330,
** Boston, MA  02111-1307, USA.
**
** Author contact information:
**   drh@hwaci.com
**   http://www.hwaci.com/drh/
**
*******************************************************************************
**
** This file contains code to implement the basic web page look and feel.
**
*/
#include "config.h"
#include "style.h"


/*
** Elements of the submenu are collected into the following
** structure and displayed below the main menu by style_header().
**
** Populate this structure with calls to style_submenu_element()
** prior to calling style_header().
*/
static struct Submenu {
  const char *zLabel;
  const char *zTitle;
  const char *zLink;
} aSubmenu[30];
static int nSubmenu = 0;

/*
** Add a new element to the submenu
*/
void style_submenu_element(
  const char *zLabel,
  const char *zTitle,
  const char *zLink
){
  assert( nSubmenu < sizeof(aSubmenu)/sizeof(aSubmenu[0]) );
  aSubmenu[nSubmenu].zLabel = zLabel;
  aSubmenu[nSubmenu].zTitle = zTitle;
  aSubmenu[nSubmenu].zLink = zLink;
  nSubmenu++;
}

/*
** Compare two submenu items for sorting purposes
*/
static int submenuCompare(const void *a, const void *b){
  const struct Submenu *A = (const struct Submenu*)a;
  const struct Submenu *B = (const struct Submenu*)B;
  return strcmp(A->zLabel, B->zLabel);
}

/*
** Draw the header.
*/
void style_header(const char *zTitle){
  const char *zLogInOut = "Logout";
  login_check_credentials();
  @ <html>
  @ <head>
  @ <title>%s(zTitle)</title>
  @ <link rel="alternate" type="application/rss+xml" title="RSS Feed" href="%s(g.zBaseURL)/timeline.rss">
  @ <link rel="stylesheet" href="%s(g.zBaseURL)/style.css" type="text/css" media="screen">
  @ </head>
  @ <body>
  @ <div id="page-title">%s(zTitle)</div>
  @ <div id="login-status">
  if( g.zLogin==0 ){
    @ not logged in
    zLogInOut = "Login";
  }else{
    @ logged in as %h(g.zLogin)
  }
  @ </div>
  @ <div id="main-menu">
  @ <a href="%s(g.zBaseURL)/index">Home</a>
  if( g.okRead ){
    @ | <a href="%s(g.zBaseURL)/leaves">Leaves</a>
    @ | <a href="%s(g.zBaseURL)/timeline">Timeline</a>
  }
  if( g.okRdWiki ){
    @ | <a href="%s(g.zBaseURL)/wiki">Wiki</a>
  }
#if 0
  @ | <font color="#888888">Search</font>
  @ | <font color="#888888">Ticket</font>
  @ | <font color="#888888">Reports</font>
#endif
  if( g.okSetup ){
    @ | <a href="%s(g.zBaseURL)/setup">Setup</a>
  }
  if( !g.noPswd ){
    @ | <a href="%s(g.zBaseURL)/login">%s(zLogInOut)</a>
  }
  @ </div>
  if( nSubmenu>0 ){
    @ <div id="sub-menu">
    int i;
    qsort(aSubmenu, nSubmenu, sizeof(aSubmenu[0]), submenuCompare);
    for(i=0; i<nSubmenu; i++){
      struct Submenu *p = &aSubmenu[i];
      char *zTail = i<nSubmenu-1 ? " | " : "";
      if( p->zLink==0 ){
        @ <span class="label">%h(p->zLabel)</span>
        @ <span class="tail">%s(zTail)</span>
      }else{
        @ <a class="label" href="%T(p->zLink)">%h(p->zLabel)</a>
        @ <span class="tail">%s(zTail)</span>
      }
    }
    @ </div>
  }
  @ <div id="page">
  g.cgiPanic = 1;
}

/*
** Draw the footer at the bottom of the page.
*/
void style_footer(void){
  /* end the <div id="page"> from style_header() */
  @ </div>
  @ <div id="style-footer">
  @ Fossil version %s(MANIFEST_VERSION) %s(MANIFEST_DATE)
  @ </div>
}

/*
** WEBPAGE: index
** WEBPAGE: home
** WEBPAGE: not_found
*/
void page_index(void){
  char *zHome = db_get("homepage", 0);
  if( zHome ){
    g.zExtra = zHome;
    g.okRdWiki = 1;
    wiki_page();
  }else{
    style_header("Main Title Page");
    @ No homepage configured for this server
    style_footer();
  }
}

/*
** TODO: COPIED FROM WIKI.C... BAD
*/
/*
** Create a fake replicate of the "vfile" table as a TEMP table
** using the manifest identified by manid.
*/
static void style_create_fake_vfile(int manid){
  static const char zVfileDef[] = 
    @ CREATE TEMP TABLE vfile(
    @   id INTEGER PRIMARY KEY,     -- ID of the checked out file
    @   vid INTEGER REFERENCES blob, -- The version this file is part of.
    @   chnged INT DEFAULT 0,       -- 0:unchnged 1:edited 2:m-chng 3:m-add
    @   deleted BOOLEAN DEFAULT 0,  -- True if deleted 
    @   rid INTEGER,                -- Originally from this repository record
    @   mrid INTEGER,               -- Based on this record due to a merge
    @   pathname TEXT,              -- Full pathname
    @   UNIQUE(pathname,vid)
    @ );
    ;
  db_multi_exec(zVfileDef);
  load_vfile_from_rid(manid);
}


/*
** WEBPAGE: style.css
*/
void page_style_css(void){
  Stmt q;
  int id = 0;
  int rid = 0;
  int chnged = 0;
  char *zPathname = 0;
  char *z;
  
  cgi_set_content_type("text/css");

  login_check_credentials();
  if( !g.localOpen ){
    int headid = db_int(0,
       "SELECT cid FROM plink ORDER BY mtime DESC LIMIT 1"
    );
    style_create_fake_vfile(headid);
  }
  
  db_prepare(&q,
     "SELECT id, rid, chnged, pathname FROM vfile"
     " WHERE (pathname='style.css' OR pathname LIKE '%%/style.css')"
     "   AND NOT deleted"
  );
  if( db_step(&q)==SQLITE_ROW ){
    id = db_column_int(&q, 0);
    rid = db_column_int(&q, 1);
    chnged = db_column_int(&q, 2);
    if( chnged || rid==0 ){
      zPathname = db_column_malloc(&q, 3);
    }
  }
  db_finalize(&q);
  if( id ){
    Blob src;
    blob_zero(&src);
    if( zPathname ){
      zPathname = mprintf("%s/%z", g.zLocalRoot, zPathname);
      blob_read_from_file(&src, zPathname);
      free(zPathname);
    }else{
      content_get(rid, &src);
    }

    z = blob_str(&src);
    @ %s(z)
  }else{
    /* No CSS file found, use our own */
    /*
    ** Selector order: tags, ids, classes, other
    ** Content order: margin, borders, padding, fonts, colors, other 
    ** Note: Once things are finialize a bit we can collapse this and
    **       make it much smaller, if necessary. Right now, it's verbose
    **       but easy to edit.
    */
    @ body {
    @   margin: 0px;
    @   padding: 0px;
    @   background-color: white;
    @ }
    @ #page-title {
    @   padding: 10px 10px 10px 10px;
    @   font-size: 2em;
    @   font-weight: bold;
    @   background-color: #d0d9f4;
    @ }
    @ #login-status {
    @   padding: 0px 10px 10px 0px;
    @   font-size: 0.9em;
    @   text-align: right;
    @   background-color: #d0d9f4;
    @   position: absolute;
    @   top: 10;
    @   right: 0;
    @ }
    @ #main-menu {
    @   border-top: 2px solid #a0b5f4;
    @   padding: 3px 10px 1px 0px;
    @   font-size: 0.9em;
    @   text-align: center;
    @   background-color: #d0d9f4;
    @ }
    @ #sub-menu {
    @   border-bottom: 2px solid #a0b5f4;
    @   padding: 3px 10px 3px 0px;
    @   font-size: 0.9em;
    @   text-align: center;
    @   background-color: #d0d9f4;
    @ }
    @ #main-menu a:visited, #sub-menu a:visited {
    @   color: blue;
    @ }
    @ #page {
    @   padding: 10px 20px 10px 20px;
    @ }
    @ #style-footer { 
    @   font-size: 0.8em; 
    @   margin-top: 12px;
    @   padding-top: 5px;
    @   border-top: 1px solid black; 
    @ }
  }
}

/*
** WEBPAGE: test_env
*/
void page_test_env(void){
  style_header("Environment Test");
  cgi_print_all();
  style_footer();
}
