private function parse(array $data)
    {
        $schemaId = SchemaId::fromString($data['id']);

        $parameters = [
            'deprecated' => isset($data['deprecated']) && $data['deprecated'],
        ];

        if (isset($data['extends'])) {
            if ($data['extends'] == $schemaId->getCurieWithMajorRev()) {
                throw new \InvalidArgumentException(sprintf(
                    'Cannot extends yourself "%s".',
                    $schemaId->toString()
                ));
            }
            if (!$extendsSchema = SchemaStore::getSchemaById($data['extends'], true)) {
                throw new MissingSchema($data['extends']);
            }

            // recursively check that chain not pointing back to schema
            $check = $extendsSchema->getExtends();
            while ($check) {
                if ($check->getId()->getCurieWithMajorRev() == $schemaId->getCurieWithMajorRev()) {
                    throw new \InvalidArgumentException(sprintf(
                        'Invalid extends chain. Schema "%s" pointing back to you "%s".',
                        $check->getId()->toString(),
                        $schemaId->toString()
                    ));
                }

                $check = $check->getExtends();
            }

            $parameters['extends'] = $extendsSchema;
        }

        if (isset($data['mixin']) && $data['mixin']) {
            $parameters['isMixin'] = true;
        }

        // default language options
        $parameters['languages'] = $this->getLanguageOptions($data);

        if (isset($data['fields']['field'])) {
            $fieldsData = $this->fixArray($data['fields']['field'], 'name');
            if (count($fieldsData)) {
                $parameters['fields'] = [];
            }
            foreach ($fieldsData as $field) {
                if ($field = $this->getFieldDescriptor($schemaId, $field)) {
                    $parameters['fields'][] = $field;
                }
            }
        }

        if (isset($data['mixins']['curie-major'])) {
            $mixinsData = $this->fixArray($data['mixins']['curie-major']);
            if (count($mixinsData)) {
                $parameters['mixins'] = [];
            }
            foreach ($mixinsData as $curieWithMajorRev) {
                if ($mixin = $this->getMixin($schemaId, $curieWithMajorRev)) {
                    $parameters['mixins'][] = $mixin;
                }
            }
        }

        return new SchemaDescriptor($schemaId, $parameters);
    }