<?php

namespace libphonenumber\Tests\carrier;

use libphonenumber\PhoneNumber;
use libphonenumber\PhoneNumberToCarrierMapper;
use libphonenumber\PhoneNumberUtil;
use PHPUnit\Framework\TestCase;

class PhoneNumberToCarrierMapperTest extends TestCase
{
    const TEST_META_DATA_FILE_PREFIX = '/../tests/carrier/data/';
    private static $AO_MOBILE1;
    private static $AO_MOBILE2;
    private static $AO_FIXED1;
    private static $AO_FIXED2;
    private static $AO_INVALID_NUMBER;
    private static $UK_MOBILE1;
    private static $UK_MOBILE2;
    private static $UK_FIXED1;
    private static $UK_FIXED2;
    private static $UK_INVALID_NUMBER;
    private static $UK_PAGER;
    private static $US_FIXED_OR_MOBILE;
    private static $NUMBER_WITH_INVALID_COUNTRY_CODE;
    private static $INTERNATIONAL_TOLL_FREE;
    /**
     * @var PhoneNumberToCarrierMapper
     */
    protected $carrierMapper;

    public static function setUpBeforeClass()
    {
        PhoneNumberUtil::resetInstance();

        self::$AO_MOBILE1 = new PhoneNumber();
        self::$AO_MOBILE1->setCountryCode(244)->setNationalNumber(917654321);

        self::$AO_MOBILE2 = new PhoneNumber();
        self::$AO_MOBILE2->setCountryCode(244)->setNationalNumber(927654321);

        self::$AO_FIXED1 = new PhoneNumber();
        self::$AO_FIXED1->setCountryCode(244)->setNationalNumber(22254321);

        self::$AO_FIXED2 = new PhoneNumber();
        self::$AO_FIXED2->setCountryCode(244)->setNationalNumber(26254321);

        self::$AO_INVALID_NUMBER = new PhoneNumber();
        self::$AO_INVALID_NUMBER->setCountryCode(244)->setNationalNumber(101234);

        self::$UK_MOBILE1 = new PhoneNumber();
        self::$UK_MOBILE1->setCountryCode(44)->setNationalNumber(7387654321);

        self::$UK_MOBILE2 = new PhoneNumber();
        self::$UK_MOBILE2->setCountryCode(44)->setNationalNumber(7487654321);

        self::$UK_FIXED1 = new PhoneNumber();
        self::$UK_FIXED1->setCountryCode(44)->setNationalNumber(1123456789);

        self::$UK_FIXED2 = new PhoneNumber();
        self::$UK_FIXED2->setCountryCode(44)->setNationalNumber(2987654321);

        self::$UK_INVALID_NUMBER = new PhoneNumber();
        self::$UK_INVALID_NUMBER->setCountryCode(44)->setNationalNumber(7301234);

        self::$UK_PAGER = new PhoneNumber();
        self::$UK_PAGER->setCountryCode(44)->setNationalNumber(7601234567);

        self::$US_FIXED_OR_MOBILE = new PhoneNumber();
        self::$US_FIXED_OR_MOBILE->setCountryCode(1)->setNationalNumber(6502123456);

        self::$NUMBER_WITH_INVALID_COUNTRY_CODE = new PhoneNumber();
        self::$NUMBER_WITH_INVALID_COUNTRY_CODE->setCountryCode(999)->setNationalNumber(2423651234);

        self::$INTERNATIONAL_TOLL_FREE = new PhoneNumber();
        self::$INTERNATIONAL_TOLL_FREE->setCountryCode(800)->setNationalNumber(12345678);
    }

    public function setUp()
    {
        $this->carrierMapper = PhoneNumberToCarrierMapper::getInstance(self::TEST_META_DATA_FILE_PREFIX);
    }

    public function testGetNameForMobilePortableRegion()
    {
        $this->assertEquals('British carrier', $this->carrierMapper->getNameForNumber(self::$UK_MOBILE1, 'en'));
        $this->assertEquals('Brittisk operat' . \pack('H*', 'c3b6') . 'r', $this->carrierMapper->getNameForNumber(
            self::$UK_MOBILE1,
            'sv_SE'
        ));
        $this->assertEquals('British carrier', $this->carrierMapper->getNameForNumber(self::$UK_MOBILE1, 'fr'));
        // Returns an empty string because the UK implements mobile number portability.
        $this->assertEquals('', $this->carrierMapper->getSafeDisplayName(self::$UK_MOBILE1, 'en'));
    }

    public function testGetNameForNonMobilePortableRegion()
    {
        $this->assertEquals('Angolan carrier', $this->carrierMapper->getNameForNumber(self::$AO_MOBILE1, 'en'));
        $this->assertEquals('Angolan carrier', $this->carrierMapper->getSafeDisplayName(self::$AO_MOBILE1, 'en'));
    }

    public function testGetNameForFixedLineNumber()
    {
        $this->assertEquals('', $this->carrierMapper->getNameForNumber(self::$AO_FIXED1, 'en'));
        $this->assertEquals('', $this->carrierMapper->getNameForNumber(self::$UK_FIXED1, 'en'));
        // If the carrier information is present in the files and the method that assumes a valid
        // number is used, a carrier is returned
        $this->assertEquals('Angolan fixed line carrier', $this->carrierMapper->getNameForValidNumber(
            self::$AO_FIXED2,
            'en'
        ));
        $this->assertEquals('', $this->carrierMapper->getNameForValidNumber(self::$UK_FIXED2, 'en'));
    }

    public function testGetNameForFixedOrMobileNumber()
    {
        $this->assertEquals('US carrier', $this->carrierMapper->getNameForNumber(self::$US_FIXED_OR_MOBILE, 'en'));
    }

    public function testGetNameForPagerNumber()
    {
        $this->assertEquals('British pager', $this->carrierMapper->getNameForNumber(self::$UK_PAGER, 'en'));
    }

    public function testGetNameForNumberWithNoDataFile()
    {
        $this->assertEquals('', $this->carrierMapper->getNameForNumber(self::$NUMBER_WITH_INVALID_COUNTRY_CODE, 'en'));
        $this->assertEquals('', $this->carrierMapper->getNameForNumber(self::$INTERNATIONAL_TOLL_FREE, 'en'));

        $this->assertEquals('', $this->carrierMapper->getNameForValidNumber(
            self::$NUMBER_WITH_INVALID_COUNTRY_CODE,
            'en'
        ));
        $this->assertEquals('', $this->carrierMapper->getNameForValidNumber(self::$INTERNATIONAL_TOLL_FREE, 'en'));
    }

    public function testGetNameForNumberWithMissingPrefix()
    {
        $this->assertEquals('', $this->carrierMapper->getNameForNumber(self::$UK_MOBILE2, 'en'));
        $this->assertEquals('', $this->carrierMapper->getNameForNumber(self::$AO_MOBILE2, 'en'));
    }

    public function testGetNameForInvalidNumber()
    {
        $this->assertEquals('', $this->carrierMapper->getNameForNumber(self::$UK_INVALID_NUMBER, 'en'));
        $this->assertEquals('', $this->carrierMapper->getNameForNumber(self::$AO_INVALID_NUMBER, 'en'));
    }
}
