<?php
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *
 * ClassLoader to load Thrift library and definitions
 * Inspired from UniversalClassLoader from Symfony 2 
 *
 * @package thrift.classloader
 */

namespace Thrift\ClassLoader;

class ThriftClassLoader
{
    /**
     * Namespaces path
     * @var array
     */
    protected $namespaces = array();

    /**
     * Thrift definition paths
     * @var type
     */
    protected $definitions = array();

    /**
     * Do we use APC cache ?
     * @var boolean
     */
    protected $apc = false;

    /**
     * APC Cache prefix
     * @var string
     */
    protected $apc_prefix;

    /**
     * Set autoloader to use APC cache
     * @param boolean $apc
     * @param string $apc_prefix
     */
    public function __construct($apc = false, $apc_prefix = null)
    {
        $this->apc = $apc;
        $this->apc_prefix = $apc_prefix;
    }

    /**
     * Registers a namespace.
     *
     * @param string       $namespace The namespace
     * @param array|string $paths     The location(s) of the namespace
     */
    public function registerNamespace($namespace, $paths)
    {
        $this->namespaces[$namespace] = (array) $paths;
    }

    /**
     * Registers a Thrift definition namespace.
     *
     * @param string       $namespace The definition namespace
     * @param array|string $paths     The location(s) of the definition namespace
     */
    public function registerDefinition($namespace, $paths)
    {
        $this->definitions[$namespace] = (array) $paths;
    }

    /**
     * Registers this instance as an autoloader.
     *
     * @param Boolean $prepend Whether to prepend the autoloader or not
     */
    public function register($prepend = false)
    {
        spl_autoload_register(array($this, 'loadClass'), true, $prepend);
    }

    /**
     * Loads the given class, definition or interface.
     *
     * @param string $class The name of the class
     */
    public function loadClass($class)
    {
        if (
            (true === $this->apc && ($file = $this->findFileInApc($class))) or
            ($file = $this->findFile($class))
        )
        {
            require_once $file;
        }
    }

    /**
     * Loads the given class or interface in APC.
     * @param string $class The name of the class
     * @return string
     */
    protected function findFileInApc($class)
    {
        if (false === $file = apc_fetch($this->apc_prefix.$class)) {
            apc_store($this->apc_prefix.$class, $file = $this->findFile($class));
        }

        return $file;
    }

    /**
     * Find class in namespaces or definitions directories
     * @param string $class
     * @return string
     */
    public function findFile($class)
    {
        // Remove first backslash
        if ('\\' == $class[0])
        {
            $class = substr($class, 1);
        }

        if (false !== $pos = strrpos($class, '\\'))
        {
            // Namespaced class name
            $namespace = substr($class, 0, $pos);

            // Iterate in normal namespaces
            foreach ($this->namespaces as $ns => $dirs)
            {
                //Don't interfere with other autoloaders
                if (0 !== strpos($namespace, $ns))
                {
                    continue;
                }

                foreach ($dirs as $dir)
                {
                    $className = substr($class, $pos + 1);

                    $file = $dir.DIRECTORY_SEPARATOR.
                                 str_replace('\\', DIRECTORY_SEPARATOR, $namespace).
                                 DIRECTORY_SEPARATOR.
                                 $className.'.php';

                    if (file_exists($file))
                    {
                        return $file;
                    }
                }
            }

            // Iterate in Thrift namespaces

            // Remove first part of namespace
            $m = explode('\\', $class);

            // Ignore wrong call
            if(count($m) <= 1)
            {
                return;
            }

            $class = array_pop($m);
            $namespace = implode('\\', $m);

            foreach ($this->definitions as $ns => $dirs)
            {
                //Don't interfere with other autoloaders
                if (0 !== strpos($namespace, $ns))
                {
                    continue;
                }

                foreach ($dirs as $dir)
                {
                    /**
                     * Available in service: Interface, Client, Processor, Rest
                     * And every service methods (_.+)
                     */
                    if(
                        0 === preg_match('#(.+)(if|client|processor|rest)$#i', $class, $n) and
                        0 === preg_match('#(.+)_[a-z0-9]+_(args|result)$#i', $class, $n)
                    )
                    {
                        $className = 'Types';
                    }
                    else
                    {
                        $className = $n[1];
                    }

                    $file = $dir.DIRECTORY_SEPARATOR .
                                 str_replace('\\', DIRECTORY_SEPARATOR, $namespace) .
                                 DIRECTORY_SEPARATOR .
                                 $className . '.php';

                    if (file_exists($file))
                    {
                        return $file;
                    }
                }
            }
        }
    }
}
