<?php
session_start();
$lifetime = 3600*24*10; // 10 days
setcookie(session_name(),session_id(),time()+$lifetime);
$_SESSION['last_access'] = time();  // DOn't time out

header("Expires: Mon, 26 Jul 2010 05:00:00 GMT");
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
header("Cache-Control: no-store, no-cache, must-revalidate"); // HTTP/1.1
header("Cache-Control: post-check=0, pre-check=0", false);
header("Pragma: no-cache");                                   // HTTP/1.0

$G_SALT = '$5$rounds=5000$usesomesillystringforsalt$';

$fullurl = (!empty($_SERVER['HTTPS']) ? 'https' : 'http') . '://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
if (preg_match("/www\./", $fullurl))
{
   $fullurl = preg_replace("/www\./", "", $fullurl);
   header("Location: $fullurl",TRUE, 301);
}


$BASE_DIR = $_SERVER['DOCUMENT_ROOT'];
$_HOLIDAY_CACHE = null;
$_STATE_CACHE = null;
$_USERNAME_CACHE = null;
$_FAVORITE_CACHE = null;
$_DISPLAY_COUNT_CACHE = null;
$_DISPLAY_HOLIDAY_CACHE = null;

if (isset($_GET['maxW']))
{
   $_SESSION['screenwidth'] = $_GET['maxW'];
   echo("<body>width = " . $_GET['maxW'] . "</body>\n");
   exit(0);
}


$db = "";
try {
   $db = new PDO("sqlite:data/display.db");
   $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e)
{
   echo "Can't read database - ";
   echo $e->getMessage();
   exit(1);
}



require_once "pages/BasePage.php";
require_once "lib/ui.php";

/*
|| Array of Availage Pages
*/   
$availPages = array(
   array(
      "label"    => "Home",
      "id"       => "home",
      "class"    => "HomePage",
      "subTitle" => "Christmas Light Displays Near You",
      "menu"     => "Y",
   ),
   array(
      "label"    => "Displays",
      "id"       => "displays",
      "class"    => "DisplayPage",
      "subTitle" => "List of displays",
      "menu"     => "Y",
   ),
   array(
      "label"    => "Tags",
      "id"       => "searchtag",
      "class"    => "SearchTagPage",
      "subTitle" => "Search by Tag",
//      "menuid"   => "search",
      "menu"     => "Y",
   ),
   array(
      "label"    => "Map",
      "id"       => "map",
      "class"    => "StatePage",
      "subTitle" => "Map",
      "menu"     => "Y",
   ),
   array(
      "label"    => "State Map",
      "id"       => "state",
      "menuid"   => "map",
      "class"    => "StatePage",
      "subTitle" => "Displays by State",
      "menu"     => "N",
   ),
   array(
      "label"    => "Contributors",
      "id"       => "contrib",
      "class"    => "TeamPage",
      "subTitle" => "Contributors",
      "menu"     => "Y",
   ),
   array(
      "label"    => "Contributor",
      "id"       => "user",
      "menuid"   => "contrib",
      "class"    => "UserPage",
      "subTitle" => "User Details",
      "menu"     => "N",
   ),
   array(
      "label"    => "My Account",
      "id"       => "account",
      "class"    => "AccountPage",
      "subTitle" => "My Account",
      "menu"     => "Y",
   ),
   array(
      "label"    => "Tools",
      "id"       => "tools",
      "class"    => "ToolPage",
      "subTitle" => "Website Tools",
      "menu"     => "N",
   ),
   array(
      "label"    => "Map Tool",
      "id"       => "toolmap",
      "menuid"   => "tools",
      "class"    => "ToolMapPage",
      "subTitle" => "Tools for Developers: Map",
      "menu"     => "N",
   ),
   array(
      "label"    => "Logo Tool",
      "id"       => "toollogo",
      "menuid"   => "tools",
      "class"    => "ToolLogoPage",
      "subTitle" => "Tools for Developers: Logo",
      "menu"     => "N",
   ),
   array(
      "label"    => "RSS Tool",
      "id"       => "toolrss",
      "menuid"   => "tools",
      "class"    => "ToolRSSPage",
      "subTitle" => "Tools for Developers: RSS Feed",
      "menu"     => "N",
   ),
   array(
      "label"    => "Favorite Tool",
      "id"       => "toolfavorite",
      "menuid"   => "tools",
      "class"    => "ToolFavoritePage",
      "subTitle" => "Tools for Developers: Favorites",
      "menu"     => "N",
   ),
   array(
      "label"    => "Favorite Tool (V2)",
      "id"       => "toolfavorite2",
      "menuid"   => "tools",
      "class"    => "ToolFavoritePagev2",
      "subTitle" => "Tools for Developers: Favorites",
      "menu"     => "N",
   ),
   array(
      "label"    => "About",
      "id"       => "about",
      "class"    => "AboutPage",
      "subTitle" => "About Us",
      "menu"     => "N",
   ),
   array(
      "label"    => "Terms",
      "id"       => "terms",
      "menuid"   => "about",
      "class"    => "TermsPage",
      "subTitle" => "Terms and Conditions",
      "menu"     => "N",
   ),
   array(
      "label"    => "FAQs",
      "id"       => "faq",
      "menuid"   => "about",
      "class"    => "FAQPage",
      "subTitle" => "Frequently Asked Questions",
      "menu"     => "N",
   ),
   array(
      "label"    => "Attribution",
      "id"       => "attr",
      "menuid"   => "about",
      "class"    => "AttrPage",
      "subTitle" => "Attribution",
      "menu"     => "N",
   ),
   array(
      "label"    => "ShowOne",
      "id"       => "single",
      "menuid"   => "displays",
      "class"    => "SinglePage",
      "subTitle" => "Displays",
      "menu"     => "N",
   ),
   array(
      "label"    => "History",
      "id"       => "history",
      "menuid"   => "displays",
      "class"    => "HistoryPage",
      "subTitle" => "Display History",
      "menu"     => "N",
   ),
   array(
      "label"    => "Edit",
      "id"       => "edit",
      "menuid"   => "displays",
      "class"    => "EditPage",
      "subTitle" => "Displays",
      "menu"     => "N",
   ),
   array(
      "label"    => "Login",
      "id"       => "login",
      "menuid"   => "account",
      "class"    => "LoginPage",
      "subTitle" => "Login",
      "menu"     => "N",
   ),
   array(
      "label"    => "Register",
      "id"       => "register",
      "menuid"   => "account",
      "class"    => "RegisterPage",
      "subTitle" => "Register",
      "menu"     => "N",
   ),
   array(
      "label"    => "Logout",
      "id"       => "logout",
      "menuid"   => "home",
      "class"    => "LogoutPage",
      "subTitle" => "Logout",
      "menu"     => "N",
   ),
);

/*
|| Canonical origin for the site.  Used to build the absolute URLs that
|| rel=canonical and the Open Graph tags require.
*/
function siteOrigin()
{
   // Deliberately fixed rather than taken from HTTP_HOST: the canonical URL
   // has to name the one address we want indexed, whatever host header the
   // request happened to arrive on.
   return "https://cooldisplays.net";
}

/*
|| The canonical URL for this page.
||
|| This must be a URL that actually resolves, so it uses the real query string
|| form.  (analyticsPagePath() below produces prettier synthetic paths, but
|| those are labels for reporting only -- nothing serves them.)  If the URLs
|| are ever rewritten to real paths, this is the one place to change.
*/
function canonicalPath($pageId)
{
   if (strcmp($pageId, "home") == 0)
      return "/";

   $path = "/index.php?page=" . rawurlencode($pageId);

   if (strcmp($pageId, "single") == 0 && isset($_GET['id']))
      $path .= "&id=" . (int) $_GET['id'];
   else if (strcmp($pageId, "history") == 0 && isset($_GET['id']))
      $path .= "&id=" . (int) $_GET['id'];
   else if (strcmp($pageId, "user") == 0 && isset($_GET['id']))
      $path .= "&id=" . (int) $_GET['id'];
   else if (strcmp($pageId, "state") == 0 && isset($_GET['state']))
      $path .= "&state=" . rawurlencode(preg_replace('/[^A-Za-z0-9]/', '', $_GET['state']));
   else if (strcmp($pageId, "displays") == 0 && isset($_GET['tag']))
      $path .= "&tag=" . (int) $_GET['tag'];

   return $path;
}

/*
|| Shorten a block of text to fit a meta description without cutting a word in
|| half.  Google renders roughly 155 characters.
*/
function seoTruncate($text, $limit = 155)
{
   $text = trim(preg_replace('/\s+/', ' ', $text));
   if (strlen($text) <= $limit)
      return $text;

   $text = substr($text, 0, $limit - 1);
   $space = strrpos($text, ' ');
   if ($space !== false and $space > $limit / 2)
      $text = substr($text, 0, $space);

   return rtrim($text, " ,.;:-") . "\xE2\x80\xA6";
}

/*
|| Escape for use inside a double quoted HTML attribute.
*/
function attr($text)
{
   return htmlspecialchars($text, ENT_QUOTES, "UTF-8");
}

/*
|| Build a clean, readable page path for Google Analytics.
||
|| Everything on the site is served by index.php with the real content selected
|| by query parameters, so GA4 would otherwise report a single "/index.php" row.
|| Mapping the deep links onto synthetic paths ("/display/121", "/state/OH")
|| makes the standard Pages and screens report useful without having to switch
|| dimensions.  $pageId has already been matched against $availPages, so it is
|| safe to echo.
*/
function analyticsPagePath($pageId)
{
   $path = "/" . $pageId;

   if (strcmp($pageId, "single") == 0 && isset($_GET['id']))
      $path = "/display/" . (int) $_GET['id'];
   else if (strcmp($pageId, "user") == 0 && isset($_GET['id']))
      $path = "/user/" . (int) $_GET['id'];
   else if (strcmp($pageId, "state") == 0 && isset($_GET['state']))
      $path = "/state/" . preg_replace('/[^A-Za-z0-9]/', '', $_GET['state']);
   else if (strcmp($pageId, "displays") == 0 && isset($_GET['tag']))
      $path = "/displays/tag/" . (int) $_GET['tag'];
   else if (strcmp($pageId, "home") == 0)
      $path = "/";

   return $path;
}

/*
|| Find the page to display, defaulting to "home"
*/
$pageId   = "home";
$menuId   = $pageId;
$subTitle = "Christmas Light Displays Near You";
if (isset($_GET['page']))
{
   foreach ($availPages as $menuItem)
   {
      if (strcmp($_GET['page'], $menuItem['id']) == 0)
      {
         $pageId = $_GET['page'];
         $menuId = $pageId;
         $subTitle = $menuItem['subTitle'];
         if (isset($menuItem['menuid']))
            $menuId = $menuItem['menuid'];  // Highlight Override!
      }
   }
}

/*
|| Now that we know the page, load the correct class
*/
foreach ($availPages as $menuItem)
{
   if (strcmp($pageId, $menuItem['id']) == 0)
   {
       require "pages/" . $menuItem['class'] . ".php";
       $bodyObject = new $menuItem['class']();
   }
}

/*
|| Send any special headers
*/
$bodyObject->httpheader();

/*
|| If the page is for an item that does not exist, say so with the status
|| code.  Serving "Invalid Display ID" as 200 OK makes it a soft 404: search
|| engines keep the URL, keep recrawling it, and may index the error.
*/
$notFound = $bodyObject->isNotFound();
if ($notFound)
   header("HTTP/1.1 404 Not Found", true, 404);

if (strcmp("UNKNOWN", $bodyObject->title()) != 0)
   $subTitle = $bodyObject->title();

/*
|| Assemble the SEO metadata for this page.  $subTitle is the page specific
|| half of the <title>; the pages supply the rest through the BasePage hooks.
*/
$canonical   = siteOrigin() . canonicalPath($pageId);
$pageTitle   = $subTitle . " | CoolDisplays.Net";
$description = $bodyObject->metaDescription();
if (strcmp($description, "") == 0)
   $description = "CoolDisplays.Net is a directory of outdoor Christmas light "
                . "and holiday displays across the United States.  Find lights "
                . "near you, with photos, maps and driving directions.";
$description = seoTruncate($description);

$ogImage = $bodyObject->ogImage();
if (strcmp($ogImage, "") == 0)
   $ogImage = siteOrigin() . "/images/logo/RGB/logo_rgb_270x129.png";

$robots  = $bodyObject->robotsMeta();
$jsonLd  = $bodyObject->jsonLd();

/*
|| A 404 gets no canonical, no Open Graph and no structured data: there is no
|| page here to describe, and pointing a canonical at a missing URL only
|| invites the crawler back.
*/
if ($notFound)
{
   $subTitle  = "Page Not Found";
   $pageTitle = $subTitle . " | CoolDisplays.Net";
   $robots    = "noindex,follow";
   $canonical = "";
   $jsonLd    = null;
}

?><!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
    <meta name="theme-color" content="#070d19">
    <link rel="preconnect" href="https://fonts.googleapis.com">
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
    <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Bricolage+Grotesque:opsz,wght@12..96,600;12..96,800&amp;family=Figtree:wght@400;500;600;700&amp;display=swap">
    <link rel="stylesheet" href="style.php?v=1302" >

<?php
    /*
    || The Maps API is render blocking, so only the pages that actually draw a
    || map pay for it.
    */
    if ($bodyObject->needsMaps())
    {
?>
    <script type="text/javascript" src="https://maps.google.com/maps/api/js?key=AIzaSyB8l-4-oAlAW16pHHcQ2ncSxofVZx3b8l8"></script>
<?php
    }
?>
    <?php $bodyObject->head(); ?>

    <title><?php echo attr($pageTitle) ?></title>
    <meta name="description" content="<?php echo attr($description) ?>">
<?php
    if (strcmp($canonical, "") != 0)
       echo("    <link rel=\"canonical\" href=\"" . attr($canonical) . "\">\n");
    if (strcmp($robots, "") != 0)
       echo("    <meta name=\"robots\" content=\"" . attr($robots) . "\">\n");

    if (! $notFound)
    {
?>

    <meta property="og:type" content="website">
    <meta property="og:site_name" content="CoolDisplays.Net">
    <meta property="og:title" content="<?php echo attr($pageTitle) ?>">
    <meta property="og:description" content="<?php echo attr($description) ?>">
    <meta property="og:url" content="<?php echo attr($canonical) ?>">
    <meta property="og:image" content="<?php echo attr($ogImage) ?>">
    <meta name="twitter:card" content="summary_large_image">
    <meta name="twitter:title" content="<?php echo attr($pageTitle) ?>">
    <meta name="twitter:description" content="<?php echo attr($description) ?>">
    <meta name="twitter:image" content="<?php echo attr($ogImage) ?>">
<?php
    }
?>
<?php
    if ($jsonLd !== null)
    {
       echo("    <script type=\"application/ld+json\">\n");
       echo(json_encode($jsonLd, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
       echo("\n    </script>\n");
    }
?>

<!-- Google Analytics (GA4) -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-859VVDMZGB"></script>
<script>
  window.dataLayer = window.dataLayer || [];
  function gtag(){dataLayer.push(arguments);}
  gtag('js', new Date());

  gtag('config', 'G-859VVDMZGB', {
    'page_path': '<?php echo analyticsPagePath($pageId); ?>'
  });
</script>
<!-- End Google Analytics -->

</head>
<body <?php $bodyObject->bodyOptions(); ?>>
    <a class="skip-link" href="#main">Skip to content</a>
    <?php addMenu($menuId); ?>

    <main id="main" class="site-main">
<?php
       $bodyObject->body();

       // Pages still being migrated may print secondary navigation here.
       ob_start();
       $bodyObject->sidebar();
       $aside = trim(ob_get_clean());
       if (strcmp($aside, "") != 0)
          echo("<aside class=\"page-aside\">" . $aside . "</aside>");
?>
    </main>

    <?php siteFooter(); ?>
    <?php tabBar($menuId); ?>

    <!-- Lightbox for pictures / videos -->
    <div id="coolLightbox" class="cool-lightbox" role="dialog" aria-modal="true" aria-label="Photos and videos">
      <button type="button" class="cool-lightbox-close" aria-label="Close" title="Close (Esc)">&times;</button>
      <button type="button" class="lb-nav lb-prev" aria-label="Previous"><?php echo icon('chevron') ?></button>
      <div id="coolLightboxContent" class="cool-lightbox-content"></div>
      <button type="button" class="lb-nav lb-next" aria-label="Next"><?php echo icon('chevron') ?></button>
      <div class="lb-count" aria-live="polite"></div>
    </div>
    </div>

    <script src="https://code.jquery.com/jquery-3.7.1.min.js" integrity="sha256-/JqT3SQfawRcv/BIHPThkBvs0OEvtFFmqPF/lYI/Cxo=" crossorigin="anonymous"></script>
    <script src="/static/merged.js?v=1403" type="text/javascript"></script>

<script type="text/javascript">
<?php
    if (getUserID() > 0)
    {
       echo("coolbase.loggedIn='Y';\n");
    }
?>

</script>
    <?php $bodyObject->footer(); ?>
</body>
</html>

<?php

/*
|| Primary navigation, in display order.  Labels come from $availPages.
*/
function navItems()
{
   global $availPages;
   $order = array("displays", "map", "searchtag", "contrib");
   $items = array();
   foreach ($order as $id)
   {
      foreach ($availPages as $p)
      {
         if (strcmp($p['id'], $id) == 0)
            $items[] = array("id" => $id, "label" => $p['label'], "ids" => array($id));
      }
   }
   // Website tools work signed out too (except My Favorites), so list them here.
   $items[] = array("id" => "tools", "label" => "Tools",
                    "ids" => array("tools", "toollogo", "toolmap", "toolrss", "toolfavorite", "toolfavorite2"));
   return $items;
}

function isSignedIn()
{
   return (hasOpenID() or (getUserID() > 0));
}

function addMenu($currentId)
{
   $signedIn = isSignedIn();
   $username = (getUserID() > 0) ? getUsername(getUserID(), "N") : "";
?>
   <header class="site-header">
     <div class="site-header-inner">
       <a class="wordmark" href="/"><span class="bulb" aria-hidden="true"></span>CoolDisplays</a>
       <nav class="primary-nav" aria-label="Main">
<?php
   foreach (navItems() as $item)
   {
      $current = in_array($currentId, $item['ids'], true) ? ' aria-current="page"' : '';
      echo('<a href="/index.php?page=' . $item['id'] . '"' . $current . '>' . $item['label'] . "</a>\n");
   }
?>
       </nav>
       <span class="header-spacer"></span>
       <form class="site-search" role="search" method="GET" action="/index.php">
         <input type="hidden" name="page" value="displays">
         <label class="visually-hidden" for="searchbox">Search displays</label>
         <input id="searchbox" name="search" type="search" placeholder="City, ZIP or display name" autocomplete="off">
       </form>
       <div class="account-area">
         <a class="btn btn-pri btn-sm" href="<?php echo $signedIn ? "/index.php?page=edit" : "/index.php?page=login" ?>"><?php echo icon('plus') ?> Add display</a>
<?php if ($signedIn) { ?>
         <details class="account-menu">
           <summary class="btn btn-sec btn-sm"><?php echo icon('user') ?> <?php echo htmlspecialchars($username !== "UNKNOWN" ? $username : "Account", ENT_QUOTES, "UTF-8") ?> <?php echo icon('chevron') ?></summary>
           <div class="account-menu-list">
             <a href="/index.php?page=account">My account</a>
             <a href="/index.php?page=account#favorites">My favorites</a>
             <a href="/index.php?page=tools">Website tools</a>
             <a href="/index.php?page=logout">Sign out</a>
           </div>
         </details>
<?php } else { ?>
         <a class="btn btn-sec btn-sm" href="/index.php?page=login">Sign in</a>
<?php } ?>
       </div>
       <button type="button" class="icon-btn" data-action="toggle-search" aria-label="Search" aria-expanded="false" onclick="coolui.toggleSearch()"><?php echo icon('search') ?></button>
       <button type="button" class="icon-btn" data-action="open-menu" aria-label="Menu" aria-haspopup="dialog" onclick="coolui.openMenu()"><?php echo icon('menu') ?></button>
     </div>
     <form class="mobile-search" role="search" method="GET" action="/index.php">
       <input type="hidden" name="page" value="displays">
       <label class="visually-hidden" for="searchboxMobile">Search displays</label>
       <input id="searchboxMobile" name="search" type="search" placeholder="City, ZIP or display name" autocomplete="off">
     </form>
   </header>

   <dialog id="menuSheet" class="menu-sheet" aria-label="Menu">
     <div class="grab" aria-hidden="true"></div>
     <div class="sheet-head">
       <?php if ($signedIn) { ?>
         <strong><?php echo htmlspecialchars($username, ENT_QUOTES, "UTF-8") ?></strong>
       <?php } else { ?>
         <a class="btn btn-pri btn-sm" href="/index.php?page=login">Sign in</a>
       <?php } ?>
       <button type="button" class="icon-btn" style="display:grid" aria-label="Close menu" onclick="coolui.closeMenu()"><?php echo icon('x') ?></button>
     </div>
     <a class="item" href="<?php echo $signedIn ? "/index.php?page=edit" : "/index.php?page=login" ?>"><?php echo icon('plus') ?> Add a display</a>
     <a class="item" href="/index.php?page=account#favorites"><?php echo icon('heart') ?> My favorites</a>
     <a class="item" href="/index.php?page=account"><?php echo icon('user') ?> My account</a>
     <a class="item" href="/index.php?page=contrib"><?php echo icon('users') ?> Contributors</a>
     <a class="item" href="/index.php?page=searchtag"><?php echo icon('list') ?> Browse by tag</a>
     <div class="label">Holidays</div>
     <div class="chip-row"><?php holidayChips() ?></div>
     <div class="label">Help</div>
     <a class="item" href="/index.php?page=faq"><?php echo icon('help') ?> Frequent questions</a>
     <a class="item" href="/index.php?page=tools"><?php echo icon('tool') ?> Website tools</a>
     <?php if ($signedIn) { ?>
     <a class="item" href="/index.php?page=logout" style="color:var(--muted)">Sign out</a>
     <?php } ?>
   </dialog>
<?php
}

/*
|| Holiday links as chips, used by the menu sheet.  Same URLs as the old
|| sidebar list.
*/
function holidayChips()
{
   try {
      $sql = "select id, name from tag where type = 'HOLIDAY' order by name";
      foreach (getDB()->query($sql) as $row)
      {
         echo('<a class="chip" href="/index.php?page=displays&amp;tag=' . $row['id'] . '">' . $row['name'] . "</a>\n");
      }
   } catch (PDOException $e)
   {
      handleError("holidayChips", $e, $sql);
   }
}

function siteFooter()
{
?>
   <footer class="site-footer">
     <div class="site-footer-inner">
       <a class="wordmark" href="/"><span class="bulb" aria-hidden="true"></span>CoolDisplays.Net</a>
       <a href="/index.php?page=faq">FAQ</a>
       <a href="/index.php?page=about">About</a>
       <a href="/index.php?page=tools">Website tools</a>
       <a href="/index.php?page=terms">Terms of service</a>
       <a href="/index.php?page=attr">Attribution</a>
       <a href="/rss.php">RSS</a>
     </div>
   </footer>
<?php
}

function tabBar($currentId)
{
   $tabs = array(
      array("href" => "/", "label" => "Explore", "icon" => "compass", "ids" => array("home", "displays", "single", "searchtag", "history", "edit")),
      array("href" => "/index.php?page=map", "label" => "Map", "icon" => "map", "ids" => array("map", "state")),
      array("href" => "/index.php?page=account#favorites", "label" => "Favorites", "icon" => "heart", "ids" => array()),
      array("href" => "/index.php?page=account", "label" => "Account", "icon" => "user", "ids" => array("account", "login", "register", "user")),
   );
   echo('<nav class="tabbar" aria-label="Quick links">');
   foreach ($tabs as $t)
   {
      $current = in_array($currentId, $t['ids'], true) ? ' aria-current="page"' : '';
      echo('<a href="' . $t['href'] . '"' . $current . '>' . icon($t['icon']) . '<span>' . $t['label'] . '</span></a>');
   }
   echo('</nav>');
}

function getDB()
{
   global $db;
   return $db;
}

function labledPicture($myclass, $pics, $text, $thumb)
{
   if ($thumb === ''){
      $thumb = $pics;
   }
   echo("<figure class=\"$myclass\">\n");
   echo("\t<a href=\"$pics\">\n");
   echo("\t\t<img src=\"$thumb\">\n");
   echo("\t<figcaption>$text</figcaption></a>\n");
   echo("</figure>\n");
}


function printHolidays()
{
   try {
      $dbh = getDB();
      $sql = "select id, name from tag where type = 'HOLIDAY' order by name";
      foreach ($dbh->query($sql) as $row)
      {
         echo ("<li><a href=\"/index.php?page=displays&amp;tag=");
         echo ($row['id'] . "\">");
         echo ($row['name'] );
         echo ("</a></li>\n");
      }
   } catch (PDOException $e)
   {
      handleError("printHolidays", $e, $sql );
   }
}

function printDisplaySummary($row, $mylat=0, $mylng=0)
{
   echo getDisplaySummary($row, $mylat, $mylng);
}

function getDisplaySummary($row, $mylat, $mylng)
{
   return displayCard($row, "grid", $mylat, $mylng);
}

function handleError($loc, $e, $extra = "" )
{
   echo("An ERROR has OCCURED at $loc. Please notify maintainer@cooldisplays.net <br>");
   error_log("An ERROR has OCCURED at $loc. Please notify admin@cooldisplays.net <br>");
   error_log($e->getMessage() . " -- " . $extra);
}

function showTags($displayId)
{
   $rc = "";
   try {
      $dbh = getDB();
      $sql = "select t.id, t.name from tag t, displaytag d ";
      $sql .= "where d.tagid = t.id and displayid = ? order by t.type";
      $stmt = $dbh->prepare($sql);
      $stmt->bindValue(1, $displayId, PDO::PARAM_INT);
      $stmt->execute();
      while($row = $stmt->fetch())
      {
         $rc .= "<a href=\"index.php?page=displays&amp;tag=" . $row['id'];
         $rc .= "\" class=\"tag\">" . $row['name'] . "</a> ";
      }
   } catch (PDOException $e)
   {
      handleError("getHoliday", $e, $sql );
   }

   return $rc;
}

/*
|| The holiday a display is tagged with, e.g. "Christmas" or "Halloween".
||
|| Used to write accurate page titles: the site is not Christmas only, and
|| calling a Halloween display "Christmas Lights" is both wrong and a poor
|| search result.  Falls back to Christmas, which is what the great majority
|| of displays are.
*/
function getHolidayName($displayId)
{
   global $_DISPLAY_HOLIDAY_CACHE;

   // Listing pages ask for this once per row, so load the whole mapping on
   // the first call rather than running a query per display.
   if ($_DISPLAY_HOLIDAY_CACHE === null)
   {
      $_DISPLAY_HOLIDAY_CACHE = array();
      try {
         $sql = "select d.displayid, t.name from tag t, displaytag d ";
         $sql .= "where d.tagid = t.id and t.type = 'HOLIDAY' ";
         $sql .= "order by t.name";
         foreach (getDB()->query($sql) as $row)
         {
            // order by name means the first one wins and stays put.
            if (!isset($_DISPLAY_HOLIDAY_CACHE[$row['displayid']]))
               $_DISPLAY_HOLIDAY_CACHE[$row['displayid']] = $row['name'];
         }
      } catch (PDOException $e)
      {
         handleError("getHolidayName", $e, $sql);
      }
   }

   if (isset($_DISPLAY_HOLIDAY_CACHE[$displayId]))
      return $_DISPLAY_HOLIDAY_CACHE[$displayId];

   return "Christmas";
}

function isAdmin()
{
   return (strcmp("ghormann", getUsername(getUserID(), "N")) == 0);
}

function getUsername($id, $link="Y")
{
   global $_USERNAME_CACHE;   
   if (is_null($_USERNAME_CACHE))
   {
      $_USERNAME_CACHE = array();
      try {
         $dbh = getDB();
         $sql = "select userid, username from users";
         foreach ($dbh->query($sql) as $row)
         {
            $_USERNAME_CACHE[$row['userid']] = $row['username'];
         }
      } catch (PDOException $e)
      {
         handleError("getUsername", $e, $sql );
      }
   }

   $rc = "UNKNOWN";
   if (isset($_USERNAME_CACHE[$id]))
   {
      $rc = $_USERNAME_CACHE[$id];
      if (strcmp("Y", $link) == 0)
      {
         $rc = "<a href=\"/index.php?page=user&amp;id=$id\">$rc</a>";
      }
    }

   return $rc;
}

function getAllStates()
{
   global $_STATE_CACHE;   
   getStateName('OH'); // Make sure states are loaded
   return $_STATE_CACHE;
}

function getStateName($id)
{
   global $_STATE_CACHE;   
   if (is_null($_STATE_CACHE))
   {
      $_STATE_CACHE = array();
      try {
         $dbh = getDB();
         $sql = "select initials, name from tag where type = 'STATE';";
         foreach ($dbh->query($sql) as $row)
         {
            $_STATE_CACHE[$row['initials']] = $row['name'];
         }
      } catch (PDOException $e)
      {
         handleError("getStateName", $e, $sql );
      }
   }

   $rc = "UNKNOWN";
   if (isset($_STATE_CACHE[$id]))
      $rc = $_STATE_CACHE[$id];

   return $rc;
}

function getTagName($id, $url="Y")
{
   global $_HOLIDAY_CACHE;   
   if (is_null($_HOLIDAY_CACHE))
   {
      $_HOLIDAY_CACHE = array();
      try {
         $dbh = getDB();
         $sql = "select id, name from tag;";
         foreach ($dbh->query($sql) as $row)
         {
            $_HOLIDAY_CACHE[$row['id']] = $row['name'];
         }
      } catch (PDOException $e)
      {
         handleError("getHoliday", $e, $sql );
      }
   }
   $rc = "";
   if (strcmp("Y", $url) == 0)
      $rc .= "<a href=\"index.php?page=displays&tag=$id\" class=\"tag\">";

   if (isset($_HOLIDAY_CACHE[$id])) {
      $rc .= $_HOLIDAY_CACHE[$id];
   } else {
      $rc .= "Old Tag";
   }

   if (strcmp("Y", $url) == 0)
      $rc .= "</a> ";

   return $rc;
}

function toDateString($ldate)
{
   list($sec, $min, $hour, $mday, $mon, $year) = localtime($ldate);
   $mon += 1;
   $year += 1900;
   return "$mon/$mday/$year";

}

function hasOpenID()
{
   return  (isset($_SESSION['openid']));
}

function screenWidth()
{
   $width = 1025; // Default
   if (isset($_SESSION['screenwidth']))
      $width = $_SESSION['screenwidth'];

   return $width;
}

function getUserID()
{
   if (isset($_SESSION['userid']))
   {
      return $_SESSION['userid'];
   }

   return 0;
}

function getHelpURL()
{
   return "maintainer@cooldisplays.net";
}

//
// Returns the number of miles bewteen
// Two locations.
//
function distance($lat1, $lon1, $lat2, $lon2) {

  $theta = $lon1 - $lon2;
  $dist = sin(deg2rad($lat1)) * sin(deg2rad($lat2)) +  cos(deg2rad($lat1)) * cos(deg2rad($lat2)) * cos(deg2rad($theta));
  $dist = acos($dist);
  $dist = rad2deg($dist);
  $miles = $dist * 60 * 1.1515;

  return $miles;

}

function getScore($displayid)
{
   if (getUserID() == 0)
      return -2;

   global $_FAVORITE_CACHE;   
   if (is_null($_FAVORITE_CACHE))
   {
      $_FAVORITE_CACHE = array();
      try {
         $dbh = getDB();
         $sql = "select * from favorites where userid = " . getUserID();
         foreach ($dbh->query($sql) as $row)
         {
            $_FAVORITE_CACHE[$row['displayid']] = $row['weight'];
         }
      } catch (PDOException $e)
      {
         handleError("getScoreName", $e, $sql );
      }
   }

   $rc = -1;
   if (isset($_FAVORITE_CACHE[$displayid]))
      $rc = $_FAVORITE_CACHE[$displayid];

   return $rc;
}

function getFavoriteLink($displayid, $type = "image")
{
   $score = getScore($displayid);
   if ($score == -2 && (strcmp("image", $type) == 0))
   return "";

   $link = "";
   $attr = " height=23 border=0 style=\"vertical-align:super;\" ";
   if ($score < 0)
   {
      $link = "<a href=\"javascript:coolbase.addFavorite(" . $displayid .")\">";;
      if (strcmp("image", $type) == 0)
      {
         $link .="<img src=\"images/notfavorite.png\" $attr ";
         $link .="title = \"Make Favorite\" >";
      }
      else
      {
         $link .= "Favorite";
      }
      $link .="</a>";
   } else
   {
      $link = "<a href=\"javascript:coolbase.removeFavorite(" . $displayid . ")\">";
      if (strcmp("image", $type) == 0)
      {
         $link .="<img src=\"images/favorite.png\" $attr ";
         $link .="title = \"Favorite with score of $score\">";
      }
      else
      {
         $link .= "Remove Favorite";
      }
      $link .="</a>";
   }

   return "$link";
}

function getDisplayCount()
{
   global $_DISPLAY_COUNT_CACHE;
   if (is_null($_DISPLAY_COUNT_CACHE))
   {
      $sql = "select count(1) CNT from display";
      try {
         $db = getDB();
         $stmt = $db->prepare($sql);
         $stmt->execute();
         while($row = $stmt->fetch())
         {
            $_DISPLAY_COUNT_CACHE = $row['CNT'];
         }

      } catch (PDOException $e)
      {
         handleError("getDisplayCount", $e, $sql);
      }

   }
   return $_DISPLAY_COUNT_CACHE;
}
function listStates()
   {
      echo("<li><a href=\"index.php?page=state&amp;state=USA\">United States</a></li>");
      echo("<li><a href=\"index.php?page=state&amp;state=LOC\">Near Me</a></li>");

      $sql = "select * from tag where type = 'STATE' ORDER BY name";
      try {
         $db = getDB();
         $stmt = $db->prepare($sql);
         $stmt->execute();
         while($row = $stmt->fetch())
         {
            $state = $row['name'];
            $url = "/index.php?page=state&amp;state=" . $row['initials'];
            echo("\t<li><a href=\"$url\">$state</a></li>\n");
         }

      } catch (PDOException $e)
      {
         handleError("ListStates", $e, $sql);
      }

   }

   function saveWarning()
   {
?>
    <div>
    By clicking the "Save" button, you agree to the <a href="index.php?page=terms">Terms of Service</a>, and you agree to release your contribution under the <a href="http://creativecommons.org/licenses/by-sa/3.0/legalcode" class="external">CC-BY-SA 3.0 License</a> (<a href="http://creativecommons.org/licenses/by-sa/3.0/" class="external">overview</a>). You agree that a hyperlink or URL to your profile is sufficient attribution under the Creative Commons license.
    </div>

<?php
   }

   function adminEmail()
   {
      $rc = "<a href=\"mailto:admin@cooldisplays.net\">";
      $rc .= "admin@cooldisplays.net</a>";
      return $rc;
   }
   function stripHTML($text)
   {
      return preg_replace('/<+\s*\/*\s*([A-Z][A-Z0-9]*)\b[^>]*\/*\s*>+/i', '', $text);
   
   }

   function strleft($s1, $s2) {
      return substr($s1, 0, strpos($s1, $s2));
   }

   function array_equal($a1, $a2) {
      return !array_diff($a1, $a2) && !array_diff($a2, $a1);
   }

   function fullUrl($url)
   {
      return "https://" . $_SERVER['SERVER_NAME'] . $url;
   }

   function isYes($options, $field)
   {
      if( is_object($options)) {
         if (property_exists($options,$field)) {
            return (strcmp("Y", $options->{$field}) == 0);
         }
      }

      return 0;
   }


?>
