<?php
/**
 * Fake FTP file system.
 * - Hook into WordPress with `new Loco_test_DummyFtpConnect`
 * - Use to write a file with `$file->getWriteContext()->connect( new WP_Filesystem_Debug($creds) )`
 */ 
class Loco_test_DummyFtpConnect extends Loco_hooks_Hookable {
    
    public function filter_filesystem_method(){
        return 'debug';
    }
    
}


/**
 * Dummy FTP file system.
 * WARNING: this actually modifies files - it just does it while simulating a remote connection
 * - All operations performed "direct" when authorized, else they fail.
 */
class WP_Filesystem_Debug extends WP_Filesystem_Base {
    
    private $authed;

    /**
     * @var WP_Error
     */
    public $errors;


    public function __construct( array $opt ) {
        $this->options = $opt;
        $this->method = 'ftp';
    }


    /**
     * Dummy FTP connect: requires username=foo password=xxx
     */
    public function connect() {
        $this->authed = false;
        $this->errors = new WP_Error;
        // @codeCoverageIgnoreStart
        if( empty($this->options['hostname']) ){
            $this->errors->add( 'bad_hostname', 'Debug: empty hostname');
            return false;
        }
        if( empty($this->options['username']) ){
            $this->errors->add( 'bad_username', 'Debug: empty username');
            return false;
        }
        if( $this->options['username'] !== 'foo' ) {
            $this->errors->add( 'bad_username', 'Debug: username expected to be "foo"');
            return false;
        }
        if( empty($this->options['password']) ){
            $this->errors->add( 'bad_username', 'Debug: empty password');
            return false;
        }
        if( $this->options['password'] !== 'xxx' ) {
            $this->errors->add( 'bad_password', 'Debug: password expected to be "xxx"' );
            return false;
        }
        // @codeCoverageIgnoreEnd
        $this->authed = true;
        return true;
    }


    /**
     * @return WP_Filesystem_Debug
     */
    public function disconnect(){
        $this->authed = false;
        $this->options = [];
        return $this;
    }



    /**
     * {@inheritdoc}
     * Dummy function allows exact path to be returned, subject to debugging filters
     */
    public function find_folder( $path ){
        if( WP_CONTENT_DIR === $path ){
            return loco_constant('WP_CONTENT_DIR');
        }
        return false;
    }
    
    
    /**
     * @internal
     * Proxies supposed remote call to *real* direct call, as long as instance is authorized.
     * Deliberately not extending WP_Filesystem_Direct for safety.
     */
    private function _call( $method, array $args ){
        if( $this->authed ){
            $real = Loco_api_WordPressFileSystem::direct();
            return call_user_func_array( [$real,$method], $args );
        }
        return false;
    }
    

    /**
     * {@inheritdoc}
     */
    public function is_writable( $file ){
        return $this->_call( __FUNCTION__, func_get_args() );
    }


    /**
     * {@inheritdoc}
     */
    public function chmod( $file, $mode = false, $recursive = false ){
        return $this->_call( __FUNCTION__, func_get_args() );
    }


    /**
     * {@inheritdoc}
     */
    public function copy( $source, $destination, $overwrite = false, $mode = false ){
        return $this->_call( __FUNCTION__, func_get_args() );
    }
    
    
    /**
     * {@inheritdoc}
     */
    public function put_contents( $path, $data, $mode = false ){
        return $this->_call( __FUNCTION__, func_get_args() );
    }
    
    
    /**
     * {@inheritdoc}
     */
    public function delete( $file, $recursive = false, $type = false ){
        return $this->_call( __FUNCTION__, func_get_args() );
    }
    
    
    /**
     * {@inheritdoc}
     */
    public function mkdir( $path, $chmod = false, $chown = false, $chgrp = false ){
        return $this->_call( __FUNCTION__, func_get_args() );
    }
    
    
}

