<?php
class product
{
    const TABLE = 'product';
    const DIRECTORY = 'extend/content/product/';
    const LARGE_WIDTH = 600;
    const LARGE_HEIGHT = 600;
    const MEDIUM_WIDTH = 140;
    const MEDIUM_HEIGHT = 140;
    const SMALL_WIDTH = 48;
    const SMALL_HEIGHT = 48;
    
    ////////////////////////////////////////////////////////////////////////////
    // Construct and destruct functions.
    
    ////////////////////////////////////////////////////////////////////////////
    // Overload functions.

    ////////////////////////////////////////////////////////////////////////////
    // Interface functions.
    
    public static function get($id)
    {
        return db::query()->select(self::TABLE)
                          ->where('id', $id)
                          ->execute()->fetch();
    }
    
    public static function get_by_path($category_id, $path)
    {
        return db::query()->select(self::TABLE)
                          ->where('category_id', $category_id)
                          ->where('path', $path)
                          ->limit(1)
                          ->execute()->fetch();
    }
    
    public static function get_list($category_id)
    {
        return db::query()->select(self::TABLE . ' p')
                          ->column('p.*')
                          ->where('p.category_id', $category_id)
                          ->join('meta m', array('AND', array('=', 'p.id', (object) array('type' => 'identifier', 'value' => 'm.type_id')), array('=', 'm.type', 'product')), 'left')
                          ->column('m.title meta')
                          ->execute();
    }
    
    public static function get_featured($limit = null)
    {
        $q = db::query()->select(self::TABLE . ' p')
                        ->column('p.id', 'p.path', 'p.name', 'p.image')
                        ->join(self::TABLE . '_featured pf', array('p.id', 'pf.product_id'), 'inner')
                        ->order('pf.id', 'desc');
        
        if ($limit !== null)
        {
            $q->limit($limit);
        }
        
        return $q->execute();
    }
    
    public static function get_count()
    {
        $q = db::query()->select(self::TABLE)
                        ->column(sql::raw('COUNT(id) as total'));
        $row = $q->execute()->fetch();
        return $row['total'];
    }
    
    public static function add(array $data)
    {
        db::query()->insert(self::TABLE)
                   ->column($data)
                   ->execute();
        
        $id = db::get()->get_last_id();
        unset($data['id']);
        search::save('product', $id, strip_tags(implode(' ', $data)), $data['name']);
        return $id;
    }
    
    public static function edit($id, array $data)
    {
        db::query()->update(self::TABLE)
                   ->column($data)
                   ->where('id', $id)
                   ->limit(1)
                   ->execute();
        
        unset($data['id']);
        search::save('product', $id, strip_tags(implode(' ', $data)), $data['name']);
    }
    
    public static function delete($id)
    {
        $p = db::query()->select(self::TABLE)
                        ->where('id', $id)
                        ->limit(1)
                        ->execute()->fetch();
        
        if ($p && $p['image'])
        {
            self::delete_image($p['image']);
        }
        
        foreach (db::query()->select(self::TABLE . '_image')->where('product_id', $id)->execute() as $i)
        {
            self::delete_image_extra($i['id']);
        }
        
        db::query()->delete(self::TABLE)
                   ->where('id', $id)
                   ->limit(1)
                   ->execute();
        
        search::delete('product', $id);
    }
    
    public static function save_image($id, array $file)
    {
        if (!preg_match('~((jpe?g)|(gif)|(png))$~i', $file['name']))
        {
            return;
        }
        
        $temp = self::DIRECTORY . '__temp_' . pathinfo($file['name'], PATHINFO_BASENAME);
        $target['o'] = self::DIRECTORY . pathinfo($file['name'], PATHINFO_FILENAME) . '.jpg';
        $target['l'] = self::DIRECTORY . pathinfo($file['name'], PATHINFO_FILENAME) . '-l.jpg';
        $target['m'] = self::DIRECTORY . pathinfo($file['name'], PATHINFO_FILENAME) . '-m.jpg';
        $target['s'] = self::DIRECTORY . pathinfo($file['name'], PATHINFO_FILENAME) . '-s.jpg';
        
        if (is_file($temp) || is_file($target['o']) || is_file($target['l']) || is_file($target['m']) || is_file($target['s']))
        {
            throw new exception();
        }
        
        folder::move($file['tmp_name'], $temp);
        $image = new image($temp);
        $image->save($target['o'], 100);
        folder::mode($target['o'], 0775);
        
        if ($image->width > self::LARGE_WIDTH || $image->height > self::LARGE_HEIGHT)
        {
            $image->resize(self::LARGE_WIDTH, self::LARGE_HEIGHT);
        }
        
        $image->save($target['l'], 100);
        folder::mode($target['l'], 0775);
        
        if ($image->width > self::MEDIUM_WIDTH || $image->height > self::MEDIUM_HEIGHT)
        {
            $image->resize(self::MEDIUM_WIDTH, self::MEDIUM_HEIGHT);
        }
        
        $image->save($target['m'], 100);
        folder::mode($target['m'], 0775);
        
        if ($image->width > self::SMALL_WIDTH || $image->height > self::SMALL_HEIGHT)
        {
            $image->resize(self::SMALL_WIDTH, self::SMALL_HEIGHT);
        }
        
        $image->save($target['s'], 100);
        folder::mode($target['s'], 0775);
        $image->close();
        folder::delete($temp);
        
        if ($id)
        {
            $p = db::query()->select(self::TABLE)
                            ->where('id', $id)
                            ->limit(1)
                            ->execute()->fetch();
            
            if ($p && $p['image'])
            {
                self::delete_image($p['image']);
            }
            
            db::query()->update(self::TABLE)
                       ->column('image', pathinfo($file['name'], PATHINFO_FILENAME))
                       ->where('id', $id)
                       ->limit(1)
                       ->execute();
        }
    }
    
    public static function delete_image($image)
    {
        if (is_file(self::DIRECTORY . $image . '.jpg'))
        {
            folder::delete(self::DIRECTORY . $image . '.jpg');
            folder::delete(self::DIRECTORY . $image . '-l.jpg');
            folder::delete(self::DIRECTORY . $image . '-m.jpg');
            folder::delete(self::DIRECTORY . $image . '-s.jpg');
        }
    }
    
    public static function feature($id)
    {
        self::unfeature($id);
        db::query()->insert(self::TABLE . '_featured')
                   ->column(array('product_id' => $id))
                   ->execute();
    }
    
    public static function is_featured($id)
    {
        return (boolean) count(db::query()->select(self::TABLE . '_featured')
                                          ->where('product_id', $id)
                                          ->limit(1)
                                          ->execute());
    }
    
    public static function unfeature($id)
    {
        db::query()->delete(self::TABLE . '_featured')
                   ->where('product_id', $id)
                   ->execute();
    }
    
    public static function get_views($id = null)
    {
        $q = db::query()->select(self::TABLE)
                        ->column(sql::raw('SUM(views) as total'));
        
        if ($id !== null)
        {
            $q->where('id', $id);
        }
        
        $row = $q->execute()->fetch();
        return $row['total'];
    }
    
    public static function save_view($id)
    {
        db::query()->update(self::TABLE)
                   ->column('views', sql::raw('views + 1'))
                   ->where('id', $id)
                   ->execute();
    }
    
    public static function get_image_extra($id)
    {
        return db::query()->select(self::TABLE . '_image')
                          ->where('product_id', $id)
                          ->execute();
    }
    
    public static function save_image_extra($id, array $file)
    {
        if (!preg_match('~((jpe?g)|(gif)|(png))$~i', $file['name']))
        {
            return;
        }
        
        $temp = self::DIRECTORY . '__temp_' . pathinfo($file['name'], PATHINFO_BASENAME);
        $target['o'] = self::DIRECTORY . pathinfo($file['name'], PATHINFO_FILENAME) . '.jpg';
        $target['l'] = self::DIRECTORY . pathinfo($file['name'], PATHINFO_FILENAME) . '-l.jpg';
        $target['m'] = self::DIRECTORY . pathinfo($file['name'], PATHINFO_FILENAME) . '-m.jpg';
        $target['s'] = self::DIRECTORY . pathinfo($file['name'], PATHINFO_FILENAME) . '-s.jpg';
        
        if (is_file($temp) || is_file($target['o']) || is_file($target['l']) || is_file($target['m']) || is_file($target['s']))
        {
            throw new exception();
        }
        
        folder::move($file['tmp_name'], $temp);
        $image = new image($temp);
        $image->save($target['o'], 100);
        folder::mode($target['o'], 0775);
        
        if ($image->width > self::LARGE_WIDTH || $image->height > self::LARGE_HEIGHT)
        {
            $image->resize(self::LARGE_WIDTH, self::LARGE_HEIGHT);
        }
        
        $image->save($target['l'], 100);
        folder::mode($target['l'], 0775);
        
        if ($image->width > self::MEDIUM_WIDTH || $image->height > self::MEDIUM_HEIGHT)
        {
            $image->resize(self::MEDIUM_WIDTH, self::MEDIUM_HEIGHT);
        }
        
        $image->save($target['m'], 100);
        folder::mode($target['m'], 0775);
        $image->resize(null, self::SMALL_HEIGHT);
        
        $image->save($target['s'], 100);
        folder::mode($target['s'], 0775);
        $image->close();
        folder::delete($temp);
        db::query()->insert(self::TABLE . '_image')
                   ->column('product_id', $id)
                   ->column('image', pathinfo($file['name'], PATHINFO_FILENAME))
                   ->execute();
        
        return db::get()->get_last_id();
    }
    
    public static function delete_image_extra($id)
    {
        $i = db::query()->select(self::TABLE . '_image')
                        ->where('id', $id)
                        ->limit(1)
                        ->execute()->fetch();
        
        if ($i)
        {
            db::query()->delete(self::TABLE . '_image')
                       ->where('id', $i['id'])
                       ->limit(1)
                       ->execute();
            
            self::delete_image($i['image']);
        }
    }
    
    ////////////////////////////////////////////////////////////////////////////
    // Internal functions.
}
