<?php

  /**
   * Test activeCollab roles and permissions
   *
   * @package activeCollab.modules.system
   * @subpackage models
   */
  class TestActiveCollabPermissions extends AngieModelTestCase {
    
    /**
     * Administrator role instance
     *
     * @var Role
     */
    protected $administrator;
    
    /**
     * Project manager role instance
     *
     * @var Role
     */
    protected $project_manager;
    
    /**
     * People manager role instance
     *
     * @var Role
     */
    protected $people_manager;
    
    /**
     * Employee role instance
     *
     * @var Role
     */
    protected $employee;
    
    /**
     * Client company manager role instance
     *
     * @var Role
     */
    protected $client_company_manager;
    
    /**
     * Client company employee role instance
     *
     * @var Role
     */
    protected $client_company_employee;
    
    /**
     * Set up test case
     */
    function setUp() {
      foreach(Roles::find() as $role) {
        switch($role->getName()) {
          case 'Administrator':
            $this->administrator = $role;
            break;
          case 'Project Manager':
            $this->project_manager = $role;
            break;
          case 'People Manager':
            $this->people_manager = $role;
            break;
          case 'Employee':
            $this->employee = $role;
            break;
          case 'Client Company Manager':
            $this->client_company_manager = $role;
            break;
          case 'Client Company Employee':
            $this->client_company_employee = $role;
            break;
        } // switch
      } // foreach
    } // setUp
    
    /**
     * Test loaded instances
     */
    function testIsA() {
      $this->assertIsA($this->administrator, 'Role');
      $this->assertIsA($this->project_manager, 'Role');
      $this->assertIsA($this->people_manager, 'Role');
      $this->assertIsA($this->employee, 'Role');
      $this->assertIsA($this->client_company_manager, 'Role');
      $this->assertIsA($this->client_company_employee, 'Role');
    } // testIsA
    
    /**
     * Test default set of roles
     */
    function testDefaultRoles() {
      $user = new User();
      
      // Administrator
      $this->assertTrue($this->administrator->getPermissionValue('has_system_access'));
      
      $user->setRole($this->administrator);
      
      $this->assertTrue($user->isAdministrator());
      $this->assertTrue($user->isProjectManager());
      $this->assertTrue($user->isPeopleManager());
      $this->assertTrue($user->canSeePrivate());
      
      // Project manager
      $this->assertTrue($this->project_manager->getPermissionValue('has_system_access'));
      
      $user->setRole($this->project_manager);
      
      $this->assertFalse($user->isAdministrator());
      $this->assertTrue($user->isProjectManager());
      $this->assertFalse($user->isPeopleManager());
      
      // People manager
      $this->assertTrue($this->people_manager->getPermissionValue('has_system_access'));
      
      $user->setRole($this->people_manager);
      
      $this->assertFalse($user->isAdministrator());
      $this->assertFalse($user->isProjectManager());
      $this->assertTrue($user->isPeopleManager());
      $this->assertTrue($user->canSeePrivate());
      
      // Employee
      $this->assertTrue($this->employee->getPermissionValue('has_system_access'));
      
      $user->setRole($this->employee);
      
      $this->assertFalse($user->isAdministrator());
      $this->assertFalse($user->isProjectManager());
      $this->assertFalse($user->isPeopleManager());
      $this->assertTrue($user->canSeePrivate());
      
      // Client company manager
      $this->assertTrue($this->client_company_manager->getPermissionValue('has_system_access'));
      
      $user->setRole($this->client_company_manager);
      
      $this->assertFalse($user->isAdministrator());
      $this->assertFalse($user->isProjectManager());
      $this->assertFalse($user->isPeopleManager());
      $this->assertFalse($user->canSeePrivate());
      
      // Client company employee
      $this->assertTrue($this->client_company_employee->getPermissionValue('has_system_access'));
      
      $user->setRole($this->client_company_employee);
      
      $this->assertFalse($user->isAdministrator());
      $this->assertFalse($user->isProjectManager());
      $this->assertFalse($user->isPeopleManager());
      $this->assertFalse($user->canSeePrivate());
    } // testDefaultRoles
    
    function testUserPermissions() {
      
      // Make sure that we have at least one existing administrator, so we can 
      // shuffle roles of $updater user
      $first_administrator = new User(1);
      $this->assertTrue($first_administrator->isLoaded());
      $this->assertTrue($first_administrator->isAdministrator());
      
      $client_company = new Company();
      $client_company->setName('Client Company');
      $client_company->setState(STATE_VISIBLE);
      $client_company->save();
      
      $user = new User();
      
      $user->setCompany($client_company);
      $user->setEmail('user@test.com');
      $user->setPassword('test');
      $user->setRole($this->client_company_employee);
      $user->save();
      
      $owner_company = new Company(1);
      $this->assertTrue($owner_company->isLoaded());
      
      $updater = new User();
      $updater->setEmail('update@test.com');
      $updater->setCompany($owner_company);
      $updater->setPassword('test');
      $updater->setState(STATE_VISIBLE);
      
      // ---------------------------------------------------
      //  Administrator
      // ---------------------------------------------------
      
      $updater->setRole($this->administrator);
      $updater->save();
      
      $this->assertEqual($updater->getRoleId(), $this->administrator->getId(), 'Role is set to administrator role');
      $this->assertTrue($updater->isAdministrator(), 'Updater is administrator');
      
      $this->assertTrue(Users::canAdd($updater, $client_company), 'Admin can add user to any company');
      $this->assertTrue($user->canEdit($updater), 'Admin can update any user');
      $this->assertTrue($user->canDelete($updater), 'Admin can delete any user');
      
      // ---------------------------------------------------
      //  Project Manager
      // ---------------------------------------------------
      
      $updater->setRole($this->project_manager);
      $updater->save();
      
      $this->assertEqual($updater->getRoleId(), $this->project_manager->getId(), 'Role is set to project management role');
      $this->assertTrue($updater->isProjectManager(), 'Updater is project manager');
      
      $this->assertFalse(Users::canAdd($updater, $client_company), "Project manager can't add accounts unless he has additional permissions");
      $this->assertFalse($user->canEdit($updater), "Project manager can't update user accounts, unless he has additional permissions (people management, company details management etc)");
      $this->assertFalse($user->canDelete($updater), "Project manager can't delete accounts unless he has additional permissions");
      
      // ---------------------------------------------------
      //  People Manager
      // ---------------------------------------------------
      
      
      $updater->setRole($this->people_manager);
      $updater->save();
      
      $this->assertEqual($updater->getRoleId(), $this->people_manager->getId(), 'Role is set to people management role');
      $this->assertTrue($updater->isPeopleManager(), 'Updater is people manager');
      
      $this->assertTrue(Users::canAdd($updater, $client_company), 'People manager can add user accounts to any company');
      $this->assertTrue($user->canEdit($updater), 'People manager can update any user account');
      $this->assertTrue($user->canDelete($updater), 'People manager can delete any user account');
      
      // ---------------------------------------------------
      //  Employee
      // ---------------------------------------------------
      
      $updater->setRole($this->employee);
      $updater->save();
      
      $this->assertFalse(Users::canAdd($updater, $client_company), "Employee can't create user accounts, unless he has additional permissions");
      $this->assertFalse($user->canEdit($updater), "Employee can't update any user accounts, unless he has additional permissions");
      $this->assertFalse($user->canDelete($updater), "Employee can't delete any user accounts, unless he has additional permissions");
      
      // ---------------------------------------------------
      //  Client company manager
      // ---------------------------------------------------
      
      $updater->setRole($this->client_company_manager);
      $updater->setCompany($client_company);
      $updater->save();
      
      $this->assertTrue($updater->isCompanyManager(), 'Updater is company manager');
      
      $this->assertTrue(Users::canAdd($updater, $client_company), 'Company manager can add users to the company');
      $this->assertTrue($user->canEdit($updater), 'Company manager can update any company user');
      $this->assertFalse($user->canDelete($updater), "Company manager can't delete users");
      
      // ---------------------------------------------------
      //  Client company member
      // ---------------------------------------------------
      
      $updater->setRole($this->client_company_employee);
      $updater->save();
      
      $this->assertFalse(Users::canAdd($updater, $client_company), "Client company employee can't add user accounts");
      $this->assertFalse($user->canEdit($updater), "Client company employee can't update other people accounts");
      $this->assertFalse($user->canDelete($updater), "Client company employee can't update other people accounts");
      
      // ---------------------------------------------------
      //  Self
      // ---------------------------------------------------
      
      $this->assertTrue($updater->canEdit($updater), "User can update his own account");
    } // testUserPermissions
    
//    function testCompanyPermissions() {
//      
//    } // testCompanyPermissions
//    
//    function testProjectPermissions() {
//      
//    } // testProjectPermissions
    
  }