/* (non-Javadoc)
   * @see com.wayfinder.core.shared.internal.WriteSerializable#write(java.io.DataOutputStream)
   */
  public void write(DataOutputStream dout) throws IOException {
    dout.writeInt(VERSION);

    dout.writeUTF(m_crc);
    dout.writeInt(m_langId);
    m_position.write(dout);

    dout.writeInt(m_categoryTable.length);
    dout.write(m_categoryTable);

    dout.writeInt(m_lookupTable.length);
    dout.write(m_lookupTable);

    dout.writeInt(m_stringTable.length);
    dout.write(m_stringTable);
  }
  /**
   * Create an instance from serialized data as written by {@link #write(DataOutputStream)}.
   *
   * @param din the DataInputStream to read from.
   * @throws IOException if there is an I/O error or if the storage format written is not supported
   *     by this implementation.
   */
  private CategoryTreeImpl(DataInputStream din) throws IOException {
    if (VERSION != din.readInt()) {
      throw new IOException("Invalid version");
    }

    m_crc = din.readUTF();
    m_langId = din.readInt();
    m_position = new Position();
    m_position.read(din);

    int ctLength = din.readInt();
    m_categoryTable = new byte[ctLength];
    din.readFully(m_categoryTable);

    int ltLength = din.readInt();
    m_lookupTable = new byte[ltLength];
    din.readFully(m_lookupTable);

    int stLength = din.readInt();
    m_stringTable = new byte[stLength];
    din.readFully(m_stringTable);
  }
  private void draw(
      Canvas canvas,
      MapCameraInterface mapCamera,
      LocationInformation ownLocation,
      LocationProvider provider,
      int origX,
      int origY,
      int x,
      int y,
      boolean isOnScreen) {
    int radius = ownLocation.getAccuracy();
    if (radius <= AbstractActivity.ACCURACY_MAX) {
      if (provider.getState() == LocationProvider.PROVIDER_STATE_AVAILABLE) {
        if (this.on) {
          drawMarker(canvas, ownPositionPinEnabled1, origX, origY);
        } else {
          drawMarker(canvas, ownPositionPinEnabled2, origX, origY);
        }
      } else {
        drawMarker(canvas, ownPositionPinDisabled, origX, origY);
      }
    } else {
      float screenRadius = (float) radius / (float) this.application.getMapInterface().getScale();
      Resources resources = application.getResources();
      float minRadious = resources.getDimensionPixelSize(R.dimen.location_circle_radius);

      if (screenRadius < minRadious) {
        screenRadius = minRadious;
      }

      int radiusColor = 0x4C0099DA;
      int borderColor = 0xAA0099DA;
      if (provider.getState() != LocationProvider.PROVIDER_STATE_AVAILABLE) {
        radiusColor = 0x4C999999;
        borderColor = 0xAA999999;
      }
      this.radiusPaint.setColor(radiusColor);
      this.borderPaint.setColor(borderColor);

      canvas.drawCircle(origX, origY, screenRadius, this.radiusPaint);
      canvas.drawCircle(origX, origY, screenRadius, this.borderPaint);
    }

    if (!isOnScreen) {
      int arrowSize = this.arrow.getWidth();
      int textX = x;
      int textY = y;
      Align align = Paint.Align.LEFT;
      int angle = 0;
      if (origX >= this.minX && origX <= this.maxX) {
        if (origY <= this.minY) {
          // outside the top of screen
          angle = 0;
          align = Paint.Align.CENTER;
          textY += arrowSize;
        } else if (origY >= this.maxY) {
          // outside the bottom of screen
          angle = 180;
          align = Paint.Align.CENTER;
          textY -= arrowSize;
        } else {
          // onscreen, shouldn't happen here
        }
      } else if (origY >= this.minY && origY <= this.maxY) {
        if (origX <= this.minX) {
          // outside the left of screen
          angle = 270;
          align = Paint.Align.LEFT;
          textX += arrowSize;
        } else if (origX >= this.maxX) {
          // outside the right of screen
          angle = 90;
          align = Paint.Align.RIGHT;
          textX -= arrowSize;
        } else {
          // onscreen, shouldn't happen here
        }
      } else {
        // both x and y is outside of screen�s boundaries
        if (origX >= this.maxX && origY <= this.minY) {
          // top, right
          angle = 45;
          align = Paint.Align.RIGHT;
          textX -= arrowSize;
          textY += arrowSize;
        } else if (origX >= this.maxX && origY >= this.maxY) {
          // bottom, right
          angle = 135;
          align = Paint.Align.RIGHT;
          textX -= arrowSize;
          textY -= arrowSize;
        } else if (origX <= this.minX && origY <= this.minY) {
          // top, left
          angle = 315;
          align = Paint.Align.LEFT;
          textX += arrowSize;
          textY += arrowSize;
        } else if (origX <= this.minX && origY >= this.maxY) {
          // bottom, left
          angle = 225;
          align = Paint.Align.LEFT;
          textX += arrowSize;
          textY -= arrowSize;
        } else {
          // onscreen, shouldn't happen here
        }
      }

      long[] worldCoords = mapCamera.getWorldCoordinate(x, y);
      Position position = new Position((int) worldCoords[0], (int) worldCoords[1]);
      int d = position.distanceTo(ownLocation.getMC2Position());
      FormattingResult result = this.application.getUnitsFormatter().formatDistance(d);
      String distance = result.getRoundedValue() + " " + result.getUnitAbbr();

      this.updateRotation(angle);
      canvas.drawBitmap(
          this.rotatedArrow,
          x - (this.rotatedArrow.getWidth() >> 1),
          y - (this.rotatedArrow.getHeight() >> 1),
          this.borderPaint);

      this.borderPaint.setTextAlign(align);

      this.borderPaint.setColor(0xFFFFFFFF);
      for (int i = 0; i < 9; i++) {
        if (i != 4) {
          canvas.drawText(
              distance,
              textX - (i % 3) + 1,
              textY - ((int) this.borderPaint.ascent() >> 1) - (i / 3) + 1,
              this.borderPaint);
        }
      }
      this.borderPaint.setColor(0xFF000000);
      canvas.drawText(
          distance, textX, textY - ((int) this.borderPaint.ascent() >> 1), this.borderPaint);
    }
  }