<?php  // vim:set et ts=4 sw=4 sts=4:
# Copyright (C) 2003-2014 hipplay Inc.
#
# This is UNPUBLISHED PROPRIETARY SOURCE CODE OF hipplay Inc.
# The copyright notice above does not evidence any actual or intended
# publication of such source code. The contents of this file may not
# be disclosed to third parties, copied or duplicated in any form, in
# whole or in part, without the prior written permission of
# hipplay Inc.
#
namespace HipPlayConnect\FileSystem;


use DB;
use HipPlayConnect\AxDB;
use HipPlayConnect\AxFatalErrorException;
use HipPlayConnect\Configuration\AxFeatures;
use HipPlayConnect\AxUnrecoverableErrorException;


class AxLocalFile extends AxFile
{
    // Warning: do not override static member variables, it does not work
	public static $views =
		array
		(
			'thumbnail' => array( 'width' => 115, 'height' => 115, 'dir' => '.thumbnails' ),
			'webview'   => array( 'width' => 512, 'height' => 512, 'dir' => '.webviews' )		
		);    

    // Warning: do not override static member variables, it does not work		
	private static $tables =
	    array
	    (
	        'tags'                   => array( 'tag' ),
	        'metadata'               => array( 'caption' ),
	        'asset_visitor_position' => array( 'visitor', 'position' )
	    );
		
	private $stat = null;    

    public function __construct( $fsPath, $sambaPath, $URIBuilder )
    {
        parent::__construct( $fsPath, $sambaPath, $URIBuilder );
        $this->xmlFields[] = 'parentHref';
        $this->xmlFields[] = 'path';
        $this->xmlFields[] = 'class';
    }	

	//
	// performance issue, so called on demand
	//
	private function callStat() {
		if ( !is_null( $this->stat ) )
			return;
		$this->stat = oeutil_stat( $this->fsPath ); // PERFORMANCE: 12 ms
		$this->data[ 'size'  ] = $this->stat[ 7 ];
		$this->data[ 'mtime' ] = $this->stat[ 9 ];
	}    
    
	
	public function getField( $key ) 
	{
	    if ( array_key_exists( $key, $this->data ) )
	       return $this->data[ $key ];
	    
	    switch ( $key )
	    {
			case 'mtime':
                $this->callStat();

			    // Bug 17149: VM Only:
                // if the file is a child of /home/0external, alter its mtime because the mtime of junction points does not change and we need a way to know if the device contents has changed    
			    if (
			        AxFeatures::has('isVM') &&
                    substr( $this->fsPath, 0, $l = strlen( self::EXTERNAL_FILESYSTEM ) + 1 ) == self::EXTERNAL_FILESYSTEM . '/' && // starts with /home/0external/
                    strpos( $this->fsPath, '/', $l ) === FALSE // no slash after /home/0external/
			    )
                    $this->data[ 'mtime' ] = $this->data[ 'mtime' ] - 30 + oeutil_getfilecount( $this->fsPath ) % 60;		    
                break;
			    
			case 'size' :
				$this->callStat();
				break;

            case 'class':
                $this->data[ 'class' ] = self::getClass( $this->fsPath );
                break;
	    }
	    
		return
			array_key_exists( $key, $this->data )
			? $this->data[ $key ]
			: null;
	}

    /**
     * Removes from side tables data linked to the list of fsPaths in argument
     *
     * @param array $what array of fsPaths to clean. Does not recurse
     *
     * @throws AxFatalErrorException
     * @throws AxUnrecoverableErrorException
     */
    // Warning: do not override static methods, it does not work    
    public static function cleanTablesFor( $what )
    {
        if ( !( $mDBConn = AxDB::getInstance( 'hipserv' ) ) )
            throw new AxFatalErrorException( 'Cannot connect to hipserv database' );
        
        $conditions = self::getFSPathConditions( $mDBConn, $what );
        foreach( self::$tables as $table => $dummy )
        {
            foreach( $conditions as $condition )
            {
                $strsql = "DELETE FROM `$table` WHERE " . $condition;
                if( DB::isError( $mDBConn->query( $strsql ) ) )                   
                    throw new AxUnrecoverableErrorException( "Error deleting from hipserv.$table " . $mDBConn->errorNative() );
            }
        }
    }

    public static function getClass( /* $fsPath */ )
    {
           return null;
    }
    

	/**
	 * Returns true if $name is a valid filename
	 * 
	 * @param string $name filename to check
	 * @return true if $name is a valid filename, false otherwise
	 */
	public static function isNameValid( $name )
	{
		return strlen( $name ) && substr( $name, 0, 1 ) != '.' && !preg_match( '/[<>&\*\?\/\\\\@#\$%\^":]/', $name );
	}

	/* Returns a unique (new) name for a file, keeping its extension intact */
	public static function getUniqueFile( $fsPath, $nameMod = '' )
    {
        $I = 1;
        $PathInfo = pathinfo($fsPath);
        $PathInfo[ 'basename' ] = self::getBasename( $fsPath ); // fix basename which is buggy
        if( $PathInfo['extension'] )
        {
            $Ext = '.'.$PathInfo['extension'];
            $NameRoot = substr($PathInfo['basname'], 0, strlen($PathInfo['basename']) - strlen($Ext));
        }
        else
        {
            $Ext = '';
            $NameRoot = $PathInfo['basename'];
        }
    
        do
        {
            $NewFile = $PathInfo['dirname']."/$NameRoot$nameMod$I$Ext" ;
            $I++;
            
            if($I > 1000)
               throw new AxUnrecoverableErrorException("Could not find available new name for file $fsPath or stuck in infinite loop."); 
        }
        while( file_exists($NewFile) );
    
        return $NewFile;
    }
	
	protected static function getViewDir ($view, $path)
	{
	    return self::getDirname( $path ) . '/' . self::$views[ $view ][ 'dir' ];
	}

}
