public function package(PassInterface $pass, $passName = '')
    {
        if ($pass->getSerialNumber() == '') {
            throw new \InvalidArgumentException('Pass must have a serial number to be packaged');
        }

        $this->populateRequiredInformation($pass);

        if ($this->passValidator) {
            if (!$this->passValidator->validate($pass)){
                throw new PassInvalidException('Failed to validate passbook', $this->passValidator->getErrors());
            };
        }

        $passDir = $this->preparePassDirectory($pass);

        // Serialize pass
        file_put_contents($passDir . 'pass.json', self::serialize($pass));

        // Images
        $this->prepareImages($pass, $passDir);

        // Localizations
        $this->prepareLocalizations($pass, $passDir);

        // Manifest.json - recursive, also add files in sub directories
        $manifestJSONFile = $this->prepareManifest($passDir);

        // Signature
        $this->sign($passDir, $manifestJSONFile);

        // Zip pass
        $zipFile = $this->getNormalizedOutputPath() . $this->getPassName($passName, $pass) . self::PASS_EXTENSION;
        $this->zip($passDir, $zipFile);

        // Remove temporary pass directory
        $this->rrmdir($passDir);

        return new SplFileObject($zipFile);
    }