docs: @SuppressWarnings({"checkstyle:cyclomaticcomplexity", "checkstyle:npathcomplexity"})
  	public final void readHeader() throws IOException {
  		if (!this.headerWasread) {
  			preReadingStage();
  
  			final ByteBuffer hbuffer = ByteBuffer.allocate(100);
  			final int read = this.stream.read(hbuffer);
  			if (read < 0) {
  				throw new EOFException();
  			}
  			hbuffer.rewind();
  			hbuffer.limit(read);
  
  			hbuffer.order(ByteOrder.BIG_ENDIAN);
  
  			// File Code (Big endian)
  			final int fileType = hbuffer.getInt();
  			if (fileType != SHAPE_FILE_CODE) {
  				throw new NotShapeFileException();
  			}
  
  			hbuffer.position(24);
  			// File Length in 16-bit words (Big endian)
  			final int streamFileSize = hbuffer.getInt();
  			this.fileSize = fromESRIWords(streamFileSize);
  
  			hbuffer.order(ByteOrder.LITTLE_ENDIAN);
  
  			// Version (Little endian)
  			final int version = hbuffer.getInt();
  			if (version != SHAPE_FILE_VERSION) {
  				throw new InvalidShapeFileVersionException(version, SHAPE_FILE_VERSION);
  			}
  
  			// Shape Type (Little endian)
  			this.expectedShapeType = ShapeElementType.fromESRIInteger(hbuffer.getInt());
  
  			// Xmin (Little endian)
  			this.minx = fromESRI_x(hbuffer.getDouble());
  			// Ymin (Little endian)
  			this.miny = fromESRI_y(hbuffer.getDouble());
  			// Xmax (Little endian)
  			this.maxx = fromESRI_x(hbuffer.getDouble());
  			// Ymax (Little endian)
  			this.maxy = fromESRI_y(hbuffer.getDouble());
  			this.minz = fromESRI_z(hbuffer.getDouble());
  			this.maxz = fromESRI_z(hbuffer.getDouble());
  			this.minm = fromESRI_m(hbuffer.getDouble());
  			this.maxm = fromESRI_m(hbuffer.getDouble());
  
  			if (!Double.isNaN(this.minx) && !Double.isNaN(this.maxx)
  					&& this.maxx < this.minx) {
  				final double t = this.maxx;
  				this.maxx = this.minx;
  				this.minx = t;
  			}
  
  			if (!Double.isNaN(this.miny) && !Double.isNaN(this.maxy)
  					&& this.maxy < this.miny) {
  				final double t = this.maxy;
  				this.maxy = this.miny;
  				this.miny = t;
  			}
  
  			if (!Double.isNaN(this.minz) && !Double.isNaN(this.maxz)
  					&& this.maxz < this.minz) {
  				final double t = this.maxz;
  				this.maxz = this.minz;
  				this.minz = t;
  			}
  
  			if (!Double.isNaN(this.minm) && !Double.isNaN(this.maxm)
  					&& this.maxm < this.minm) {
  				final double t = this.maxm;
  				this.maxm = this.minm;
  				this.minm = t;
  			}
  
  			this.headerWasread = true;
  			this.nextExpectedRecordIndex = 0;
  
  			postHeaderReadingStage();
  
  			initializeContentBuffer();
  
  			if (this.taskProgression != null) {
  				this.taskProgression.setProperties(this.buffer.position() + HEADER_BYTES, 0, this.fileSize, false);
  				this.taskProgression.setIndeterminate(false);
  			}
  		}
  	}