private void writeNode(Node n, EntityInfo i, XmlSerializer ser, long changeSetId, String user)
      throws IllegalArgumentException, IllegalStateException, IOException {
    ser.startTag(null, "node"); // $NON-NLS-1$
    ser.attribute(null, "id", n.getId() + ""); // $NON-NLS-1$ //$NON-NLS-2$
    ser.attribute(null, "lat", n.getLatitude() + ""); // $NON-NLS-1$ //$NON-NLS-2$
    ser.attribute(null, "lon", n.getLongitude() + ""); // $NON-NLS-1$ //$NON-NLS-2$
    if (i != null) {
      // ser.attribute(null, "timestamp", i.getETimestamp());
      // ser.attribute(null, "uid", i.getUid());
      // ser.attribute(null, "user", i.getUser());
      ser.attribute(null, "visible", i.getVisible()); // $NON-NLS-1$
      ser.attribute(null, "version", i.getVersion()); // $NON-NLS-1$
    }
    ser.attribute(null, "changeset", changeSetId + ""); // $NON-NLS-1$ //$NON-NLS-2$

    for (String k : n.getTagKeySet()) {
      String val = n.getTag(k);
      if (val.length() == 0) continue;
      ser.startTag(null, "tag"); // $NON-NLS-1$
      ser.attribute(null, "k", k); // $NON-NLS-1$
      ser.attribute(null, "v", val); // $NON-NLS-1$
      ser.endTag(null, "tag"); // $NON-NLS-1$
    }
    ser.endTag(null, "node"); // $NON-NLS-1$
  }
  public EntityInfo loadNode(Node n) {
    long nodeId = n.getId(); // >> 1;
    try {
      String res =
          sendRequest(
              SITE_API + "api/0.6/node/" + nodeId,
              "GET",
              null,
              ctx.getString(R.string.loading_poi_obj) + nodeId,
              false); //$NON-NLS-1$ //$NON-NLS-2$
      if (res != null) {
        OsmBaseStorage st = new OsmBaseStorage();
        st.parseOSM(
            new ByteArrayInputStream(res.getBytes("UTF-8")), null, null, true); // $NON-NLS-1$
        EntityId id = new Entity.EntityId(EntityType.NODE, nodeId);
        //				Node entity = (Node) st.getRegisteredEntities().get(id);
        entityInfo = st.getRegisteredEntityInfo().get(id);
        return entityInfo;
      }

    } catch (IOException e) {
      log.error("Loading node failed " + nodeId, e); // $NON-NLS-1$
      AccessibleToast.makeText(
              ctx, ctx.getResources().getString(R.string.error_io_error), Toast.LENGTH_LONG)
          .show();
    } catch (SAXException e) {
      log.error("Loading node failed " + nodeId, e); // $NON-NLS-1$
      AccessibleToast.makeText(
              ctx, ctx.getResources().getString(R.string.error_io_error), Toast.LENGTH_LONG)
          .show();
    }
    return null;
  }
  @Override
  public Node loadNode(Amenity n) {
    if (n.getId() % 2 == 1) {
      // that's way id
      return null;
    }
    long nodeId = n.getId() >> 1;
    try {
      String res =
          sendRequest(
              SITE_API + "api/0.6/node/" + nodeId,
              "GET",
              null,
              ctx.getString(R.string.loading_poi_obj) + nodeId,
              false); //$NON-NLS-1$ //$NON-NLS-2$
      if (res != null) {
        OsmBaseStorage st = new OsmBaseStorage();
        st.parseOSM(
            new ByteArrayInputStream(res.getBytes("UTF-8")), null, null, true); // $NON-NLS-1$
        EntityId id = new Entity.EntityId(EntityType.NODE, nodeId);
        Node entity = (Node) st.getRegisteredEntities().get(id);
        entityInfo = st.getRegisteredEntityInfo().get(id);
        // check whether this is node (because id of node could be the same as relation)
        if (entity != null && MapUtils.getDistance(entity.getLatLon(), n.getLocation()) < 50) {
          return entity;
        }
        return null;
      }

    } catch (IOException e) {
      log.error("Loading node failed " + nodeId, e); // $NON-NLS-1$
      AccessibleToast.makeText(
              ctx, ctx.getResources().getString(R.string.error_io_error), Toast.LENGTH_LONG)
          .show();
    } catch (SAXException e) {
      log.error("Loading node failed " + nodeId, e); // $NON-NLS-1$
      AccessibleToast.makeText(
              ctx, ctx.getResources().getString(R.string.error_io_error), Toast.LENGTH_LONG)
          .show();
    }
    return null;
  }
  private void save() {
    if (TextUtils.isEmpty(poiTypeEditText.getText())) {
      poiTypeEditText.setError(getResources().getString(R.string.please_specify_poi_type));
      return;
    }
    OsmPoint.Action action = node.getId() == -1 ? OsmPoint.Action.CREATE : OsmPoint.Action.MODIFY;
    for (Map.Entry<String, String> tag : editPoiData.getTagValues().entrySet()) {
      if (tag.getKey().equals(EditPoiData.POI_TYPE_TAG)) {
        final PoiType poiType = allTranslatedSubTypes.get(tag.getValue().trim().toLowerCase());
        if (poiType != null) {
          node.putTag(poiType.getOsmTag(), poiType.getOsmValue());
          if (poiType.getOsmTag2() != null) {
            node.putTag(poiType.getOsmTag2(), poiType.getOsmValue2());
          }
        } else {
          node.putTag(editPoiData.amenity.getType().getDefaultTag(), tag.getValue());
        }
        //					} else if (tag.tag.equals(OSMSettings.OSMTagKey.DESCRIPTION.getValue())) {
        //						description = tag.value;
      } else {
        if (tag.getKey().length() > 0) {
          node.putTag(tag.getKey(), tag.getValue());
        } else {
          node.removeTag(tag.getKey());
        }
      }
    }
    commitNode(
        action,
        node,
        mOpenstreetmapUtil.getEntityInfo(),
        "",
        false, // closeChange.isSelected(),
        new Runnable() {
          @Override
          public void run() {
            OsmEditingPlugin plugin = OsmandPlugin.getPlugin(OsmEditingPlugin.class);
            if (plugin != null) {
              List<OpenstreetmapPoint> points = plugin.getDBPOI().getOpenstreetmapPoints();
              OsmPoint point = points.get(points.size() - 1);
              if (getActivity() instanceof MapActivity) {
                MapActivity mapActivity = (MapActivity) getActivity();
                mapActivity
                    .getContextMenu()
                    .showOrUpdate(
                        new LatLon(point.getLatitude(), point.getLongitude()),
                        plugin.getOsmEditsLayer(mapActivity).getObjectName(point),
                        point);
              }
            }

            if (getActivity() instanceof MapActivity) {
              ((MapActivity) getActivity()).getMapView().refreshMap(true);
            }
            dismiss();
          }
        },
        getActivity(),
        mOpenstreetmapUtil);
  }
  @TargetApi(Build.VERSION_CODES.HONEYCOMB)
  @Override
  public View onCreateView(
      LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    final View view = inflater.inflate(R.layout.fragment_edit_poi, container, false);
    final OsmandSettings settings = getMyApplication().getSettings();
    boolean isLightTheme = settings.OSMAND_THEME.get() == OsmandSettings.OSMAND_LIGHT_THEME;

    if (savedInstanceState != null) {
      Map<String, String> mp = (Map<String, String>) savedInstanceState.getSerializable(TAGS_LIST);
      editPoiData.updateTags(mp);
    }

    Toolbar toolbar = (Toolbar) view.findViewById(R.id.toolbar);
    toolbar.setTitle(R.string.poi_create_title);
    toolbar.setNavigationIcon(R.drawable.abc_ic_ab_back_mtrl_am_alpha);
    toolbar.setNavigationOnClickListener(
        new View.OnClickListener() {
          @Override
          public void onClick(View v) {
            dismissCheckForChanges();
          }
        });

    viewPager = (ViewPager) view.findViewById(R.id.viewpager);
    String basicTitle = getResources().getString(R.string.tab_title_basic);
    String extendedTitle = getResources().getString(R.string.tab_title_advanced);
    final MyAdapter pagerAdapter =
        new MyAdapter(getChildFragmentManager(), basicTitle, extendedTitle);
    viewPager.setAdapter(pagerAdapter);
    viewPager.addOnPageChangeListener(
        new ViewPager.OnPageChangeListener() {
          @Override
          public void onPageScrolled(int i, float v, int i1) {}

          @Override
          public void onPageSelected(int i) {
            ((OnFragmentActivatedListener) pagerAdapter.getItem(i)).onFragmentActivated();
          }

          @Override
          public void onPageScrollStateChanged(int i) {}
        });

    final TabLayout tabLayout = (TabLayout) view.findViewById(R.id.tab_layout);
    tabLayout.setTabMode(TabLayout.MODE_SCROLLABLE);

    // Hack due to bug in design support library v22.2.1
    // https://code.google.com/p/android/issues/detail?id=180462
    // TODO remove in new version
    if (ViewCompat.isLaidOut(tabLayout)) {
      tabLayout.setupWithViewPager(viewPager);
    } else {
      tabLayout.addOnLayoutChangeListener(
          new View.OnLayoutChangeListener() {
            @Override
            public void onLayoutChange(
                View v,
                int left,
                int top,
                int right,
                int bottom,
                int oldLeft,
                int oldTop,
                int oldRight,
                int oldBottom) {
              tabLayout.setupWithViewPager(viewPager);
              tabLayout.removeOnLayoutChangeListener(this);
            }
          });
    }

    ImageButton onlineDocumentationButton =
        (ImageButton) view.findViewById(R.id.onlineDocumentationButton);
    onlineDocumentationButton.setOnClickListener(
        new View.OnClickListener() {
          @Override
          public void onClick(View v) {
            getActivity()
                .startActivity(
                    new Intent(
                        Intent.ACTION_VIEW,
                        Uri.parse("https://wiki.openstreetmap.org/wiki/Map_Features")));
          }
        });

    final int colorId = isLightTheme ? R.color.inactive_item_orange : R.color.dash_search_icon_dark;
    final int color = getResources().getColor(colorId);
    onlineDocumentationButton.setImageDrawable(
        getMyApplication().getIconsCache().getPaintedContentIcon(R.drawable.ic_action_help, color));
    final ImageButton poiTypeButton = (ImageButton) view.findViewById(R.id.poiTypeButton);
    poiTypeButton.setOnClickListener(
        new View.OnClickListener() {
          @Override
          public void onClick(View v) {
            DialogFragment fragment = PoiTypeDialogFragment.createInstance(editPoiData.amenity);
            fragment.show(getChildFragmentManager(), "PoiTypeDialogFragment");
          }
        });

    EditText poiNameEditText = (EditText) view.findViewById(R.id.poiNameEditText);
    poiNameEditText.addTextChangedListener(
        new TextWatcher() {
          @Override
          public void beforeTextChanged(CharSequence s, int start, int count, int after) {}

          @Override
          public void onTextChanged(CharSequence s, int start, int before, int count) {}

          @Override
          public void afterTextChanged(Editable s) {
            if (!getEditPoiData().isInEdit()) {
              if (!TextUtils.isEmpty(s)) {
                getEditPoiData().putTag(OSMSettings.OSMTagKey.NAME.getValue(), s.toString());
              } else {
                getEditPoiData().removeTag(OSMSettings.OSMTagKey.NAME.getValue());
              }
            }
          }
        });
    poiNameEditText.setText(node.getTag(OSMSettings.OSMTagKey.NAME));
    poiTypeTextInputLayout = (TextInputLayout) view.findViewById(R.id.poiTypeTextInputLayout);
    poiTypeEditText = (AutoCompleteTextView) view.findViewById(R.id.poiTypeEditText);
    poiTypeEditText.addTextChangedListener(
        new TextWatcher() {
          @Override
          public void beforeTextChanged(CharSequence s, int start, int count, int after) {}

          @Override
          public void onTextChanged(CharSequence s, int start, int before, int count) {}

          @Override
          public void afterTextChanged(Editable s) {
            if (!getEditPoiData().isInEdit()) {
              getEditPoiData().putTag(EditPoiData.POI_TYPE_TAG, s.toString());
            }
          }
        });
    poiNameEditText.setOnEditorActionListener(mOnEditorActionListener);
    poiTypeEditText.setOnEditorActionListener(mOnEditorActionListener);
    poiTypeEditText.setText(editPoiData.amenity.getSubType());

    Button saveButton = (Button) view.findViewById(R.id.saveButton);
    saveButton.setText(R.string.shared_string_save);
    saveButton.setOnClickListener(
        new View.OnClickListener() {
          @Override
          public void onClick(View v) {
            save();
          }
        });
    Button cancelButton = (Button) view.findViewById(R.id.cancelButton);
    cancelButton.setOnClickListener(
        new View.OnClickListener() {
          @Override
          public void onClick(View v) {
            FragmentManager fragmentManager = getActivity().getSupportFragmentManager();
            fragmentManager.beginTransaction().remove(EditPoiDialogFragment.this).commit();
            fragmentManager.popBackStack();
          }
        });
    setAdapterForPoiTypeEditText();
    setCancelable(false);
    return view;
  }
  @Override
  public Node commitNodeImpl(
      OsmPoint.Action action,
      final Node n,
      EntityInfo info,
      String comment,
      boolean closeChangeSet) {
    if (isNewChangesetRequired()) {
      changeSetId = openChangeSet(comment);
      changeSetTimeStamp = System.currentTimeMillis();
    }
    if (changeSetId < 0) {
      return null;
    }

    try {
      Node newN = n;
      StringWriter writer = new StringWriter(256);
      XmlSerializer ser = Xml.newSerializer();
      try {
        ser.setOutput(writer);
        ser.startDocument("UTF-8", true); // $NON-NLS-1$
        ser.startTag(null, "osmChange"); // $NON-NLS-1$
        ser.attribute(null, "version", "0.6"); // $NON-NLS-1$ //$NON-NLS-2$
        ser.attribute(null, "generator", Version.getAppName(ctx)); // $NON-NLS-1$
        ser.startTag(null, OsmPoint.stringAction.get(action));
        ser.attribute(null, "version", "0.6"); // $NON-NLS-1$ //$NON-NLS-2$
        ser.attribute(null, "generator", Version.getAppName(ctx)); // $NON-NLS-1$
        writeNode(n, info, ser, changeSetId, settings.USER_NAME.get());
        ser.endTag(null, OsmPoint.stringAction.get(action));
        ser.endTag(null, "osmChange"); // $NON-NLS-1$
        ser.endDocument();
      } catch (IOException e) {
        log.error("Unhandled exception", e); // $NON-NLS-1$
      }
      String res =
          sendRequest(
              SITE_API + "api/0.6/changeset/" + changeSetId + "/upload",
              "POST", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
              writer.getBuffer().toString(),
              ctx.getString(R.string.commiting_node),
              true);
      log.debug(res + ""); // $NON-NLS-1$
      if (res != null) {
        if (OsmPoint.Action.CREATE == action) {
          long newId = n.getId();
          int i = res.indexOf("new_id=\""); // $NON-NLS-1$
          if (i > 0) {
            i = i + "new_id=\"".length(); // $NON-NLS-1$
            int end = res.indexOf("\"", i); // $NON-NLS-1$
            if (end > 0) {
              newId = Long.parseLong(res.substring(i, end)); // << 1;
              newN = new Node(n, newId);
            }
          }
        }
        changeSetTimeStamp = System.currentTimeMillis();
        return newN;
      }
      return null;
    } finally {
      if (closeChangeSet) {
        closeChangeSet();
      }
    }
  }