<?php

    
class calibre {

        public 
$settings = array(
            
"server"    => array(
                
// calibre server details
                
"host"      => "",
                
"port"      => "8080",
                
"username"  => "",
                
"password"  => "",
            ),
            
// calibre server tokens/values
            
"start"     => 0,
            
"num"       => 20,
            
"order"     => "ascending",
            
"sort"      => "title",
            
"search"    => "",
        );

        
// .. curl data
        
private $curl_meta$curl_data;

        
// xml, object (simplexml) data
        
private $xml$object;

        
// html data
        
private $paginate;

        private 
$authors    = array();
        private 
$series     = array();
        
        public function 
__construct() {}
        
        public function 
debug() {
            
            echo 
"<pre>";
            
print_r($this);
            echo 
"</pre>";
            die;
            
        }

        private function 
fetch_query_string() {
            
            
$data $this->settings;
            
            unset(
$data["server"]);
            
            return 
"?"http_build_query($data"&amp;");
        
        }
        
        private function 
parse_response() {

            try {

                
$this->object = new SimpleXMLElement($this->curl_data);
            
                
$this->xml $this->object->asXML();

            } catch(
Exception $e) {
                throw new 
CalibreException($e->getMessage());
            }
            
        }
        
        public function 
set($settings) {
            
            if(
is_array($settings)) {

                foreach(
$settings AS $key => $value) {

                    if(empty(
$key) || empty($value)) continue;

                    
$this->settings[$key] = $value;

                }
            }
            
            return 
$this;
            
        }
        
        public function 
fetch_library() {

            if(empty(
$this->settings["server"]["host"]) || empty($this->settings["server"]["port"]))
                throw new 
CalibreException('No Server/Port Defined! <a class="button define server" href="#define">Define Server Settings</a>');

            
$qs $this->fetch_query_string();

            
$curl curl_init();

            if(!empty(
$this->settings["server"]["username"]) && !empty($this->settings["server"]["password"])) {

                
curl_setopt($chCURLOPT_USERPWD"{$this->settings["server"]["username"]}:{$this->settings["server"]["password"]}");
                
curl_setopt($chCURLOPT_HTTPAUTHCURLAUTH_ANY);

            }
            
            
curl_setopt_array($curl, array(
                
CURLOPT_RETURNTRANSFER => TRUE,
                
CURLOPT_HEADER => 0,
                
CURLOPT_USERAGENT => "",
                
CURLOPT_URL => "http://{$this->settings["server"]["host"]}/library{$qs}",
                
CURLOPT_PORT => $this->settings["server"]["port"],
                
CURLOPT_TIMEOUT => 3,
            ));
            
            
$this->curl_data curl_exec($curl);
            
$this->curl_meta curl_getinfo($curl);
            
            
curl_close($curl);

            if(
$this->curl_data === FALSE)
                throw new 
CalibreException('cURL Data is empty! Is the Server running? <a class="button define server" href="#define">Define Server Settings</a>');

            try {
                
$this->parse_response();
            } catch(
CalibreException $e) {
                throw new 
CalibreException($e->getMessage());
            }

            return 
$this;

        }

        public function 
as_json() {
            return 
json_encode($this->object);
        }

        public function 
as_object() {
            return 
$this->object;
        }
        
        public function 
as_xml() {
            return 
$this->xml;
        }
        
        private function 
page_select($page_count$current 1) {
            
            
$options = array();
            
            for(
$i 1$i <= $page_count$i++) {
                
                
$selected $i == $current "selected" "" ;
                
                
$options[] = '<option value="'$i .'" '$selected .'>'$i .'</option>';
                
            }
            
            return 
'<select class="paginate">'implode(""$options) .'</select>';
            
        }

        public function 
paginate($total) {
            
            
$page_count ceil($total $this->settings["num"]);

            
$current ceil($this->settings["start"] / $this->settings["num"]);
            
$current = empty($current) ? $current ;
            
            
$prev $current == $current ;
            
$next $current == $page_count $page_count $current ;
            
            
$links = array();

            
$links[] = '
<section class="paginate">
    <ul>
        <li class="prev">
            <a href="page/'
$prev .'" class="button">&laquo; Prev</a>
        </li>
        <li class="current">'
$this->page_select($page_count$current) .' of '$page_count .'</li>
        <li class="next">
            <a href="page/'
$next .'" class="button">Next &raquo;</a>
        </li>
    </ul>
</section>
            '
;

            
$this->paginate implode(""$links);

        }
        
        public function 
parse_html($book) {

            
$data = array();
            
            foreach(
$book->attributes() AS $key => $value) {

                if(
$key == "formats") {
                    
$data[$key] = $this->parse_formats((string) $value$data["title"], $data["id"]);
                } elseif(
$key == "authors") {
                    
$data[$key] = $this->parse_authors((string) $value);
                } elseif(
$key == "series") {
                    
$data[$key] = $this->parse_series((string) $value);
                } else {
                    
$data[$key] = (string) $value;
                }
            }

            return 
$data;
        
        }
        
        private function 
parse_formats($format$title$id) {
        
            
$formats stristr($format",") ? explode(","$format) : array($format) ;
            
            
$output = array();
            
            foreach(
$formats AS $f)
                
$output[] = '<a href="http://'$this->settings["server"]["host"] .':'$this->settings["server"]["port"] .'/get/'strtolower($f) .'/'$title .'_'$id .'.'strtolower($f) .'" class="file button">'strtoupper($f) .'</a>';
            
            return 
implode(""$output);
            
        }
        
        private function 
parse_authors($authors) {
            
            
$authors stristr($authors",") ? explode(","$authors) : array($authors) ;
            
            
$output = array();
            
            foreach(
$authors AS $author)
                
$output[] = ucwords(trim($author));

            
$this->authors array_merge($this->authors$output);

            return 
implode(""$output);
            
        }
        
        private function 
parse_series($series) {
            return empty(
$series) ? "Unknown" ucwords($series) ;
        }

        public function 
as_html() {
            
            
$books = array();

            
$attrib $this->object->attributes();
            
            
$this->paginate((int) $attrib->total);
            
            foreach(
$this->object->children() AS $key => $value) {
                
                
$book $this->parse_html($value);

                
$this->series[] = $book["series"];
                
                
$books[] = '
<article class="book">
    
    <header><h2>'
$book["title"] .'</h2></header>
    
    <section class="content">

        <section class="details float-left">
        
            <ul>
            
                <li class="author">
                    <span class="label">Author</span>
                    <span class="data">'
$book["authors"] .'</span>
                </li>
                <li class="author">
                    <span class="label">Series</span>
                    <span class="data">'
$book["series"] .'</span>
                </li>
                <li class="formats">
                    <span class="label">Download</span>
                    <span class="data">'
$book["formats"] .'</span>
                </li>

            </ul>
        
        </section>

        <section class="image float-right">

            <img src="http://'
$this->settings["server"]["host"] .':'$this->settings["server"]["port"] .'/get/cover/'$book["id"] .'" alt="Cover Image" />

        </section>
        
    </section>
    
</article>
                '
;
            }
            
            
$paginate $this->paginate;

            return 
$paginate implode(""$books) . $paginate;
            
        }

    }

    class 
CalibreException extends Exception {
        public function 
__construct($message$code 0) {
            
parent::__construct($message$code);
        }
    }
    
// 
    
$calibre = new calibre;
    
// should probably escape all this..
    
$sort   = empty($_GET['sort']) ? $calibre->settings["sort"] : $_GET['sort'] ;
    
$order  = empty($_GET['order']) ? $calibre->settings["order"] : $_GET['order'] ;
    
$search = empty($_GET['search']) ? "" $_GET['search'] ;
    
//
    
$start  = empty($_GET['start']) ? : (int) $_GET['start'] ;
    
$per_page $calibre->settings["num"];
    
// esp. this
    
$server = array(
        
"host"      => $_GET['host'],
        
"port"      => $_GET['port'],
        
"username"  => $_GET['username'],
        
"password"  => $_GET['password'],
    );
    
//
    
$settings = array(
        
"start" => $start $per_page,
        
"num"   => $per_page,
        
"sort"  => $sort,
        
"order" => $order,
        
"search"=> $search,
        
"server"=> $server,
    );

    
// try getting library as html
    
try {
        echo 
$calibre->set($settings)->fetch_library()->as_html();
    } catch(
CalibreException $e) {
        echo 
'<article class="error">'$e->getMessage() .'</article>';
    }
    
    die;
    
    
//$calibre->debug(); // very long page
    
?>