<commit_before>#include "Framework.hpp"
#include "MapStorage.hpp"

#include "../opengl/androidoglcontextfactory.hpp"

#include "../core/jni_helper.hpp"

#include "../country/country_helper.hpp"

#include "../platform/Platform.hpp"

#include "map/information_display.hpp"
#include "map/user_mark.hpp"

#include "drape_frontend/visual_params.hpp"
#include "drape_frontend/user_event_stream.hpp"
#include "drape/pointers.hpp"

#include "coding/file_container.hpp"
#include "coding/file_name_utils.hpp"

#include "geometry/angles.hpp"

#include "platform/country_file.hpp"
#include "platform/local_country_file.hpp"
#include "platform/local_country_file_utils.hpp"
#include "platform/location.hpp"
#include "platform/measurement_utils.hpp"
#include "platform/platform.hpp"
#include "platform/preferred_languages.hpp"
#include "platform/settings.hpp"

#include "base/math.hpp"
#include "base/logging.hpp"

android::Framework * g_framework = 0;

using namespace storage;
using platform::CountryFile;
using platform::LocalCountryFile;

namespace
{

::Framework * frm()
{
  return g_framework->NativeFramework();
}

}

namespace android
{

enum MultiTouchAction
{
  MULTITOUCH_UP    =   0x00000001,
  MULTITOUCH_DOWN  =   0x00000002,
  MULTITOUCH_MOVE  =   0x00000003,
  MULTITOUCH_CANCEL =  0x00000004
};

Framework::Framework()
 : m_doLoadState(true)
 , m_lastCompass(0.0)
 , m_currentMode(location::MODE_UNKNOWN_POSITION)
{
  ASSERT_EQUAL ( g_framework, 0, () );
  g_framework = this;
  m_activeMapsConnectionID = m_work.GetCountryTree().GetActiveMapLayout().AddListener(this);
}

Framework::~Framework()
{
  m_work.GetCountryTree().GetActiveMapLayout().RemoveListener(m_activeMapsConnectionID);
}

void Framework::OnLocationError(int errorCode)
{
  m_work.OnLocationError(static_cast<location::TLocationError>(errorCode));
}

void Framework::OnLocationUpdated(location::GpsInfo const & info)
{
  m_work.OnLocationUpdate(info);
}

void Framework::OnCompassUpdated(location::CompassInfo const & info)
{
  static double const COMPASS_THRASHOLD = my::DegToRad(1.0);

  /// @todo Do not emit compass bearing too often while we are passing it through nv-queue.
  /// Need to make more experiments in future.
  if (fabs(ang::GetShortestDistance(m_lastCompass, info.m_bearing)) >= COMPASS_THRASHOLD)
  {
    m_lastCompass = info.m_bearing;
    m_work.OnCompassUpdate(info);
  }
}

void Framework::UpdateCompassSensor(int ind, float * arr)
{
  m_sensors[ind].Next(arr);
}

float Framework::GetBestDensity(int densityDpi)
{
  typedef pair<int, float> P;
  P dens[] = {
      P(120, 0.75f),
      P(160, 1.0f),
      P(240, 1.5f),
      P(320, 2.0f),
      P(480, 3.0f)
  };

  int prevRange = numeric_limits<int>::max();
  int bestRangeIndex = 0;
  for (int i = 0; i < ARRAY_SIZE(dens); i++)
  {
    int currRange = abs(densityDpi - dens[i].first);
    if (currRange <= prevRange)
    {
      // it is better, take index
      bestRangeIndex = i;
      prevRange = currRange;
    }
    else
      break;
  }

  return dens[bestRangeIndex].second;
}

void Framework::MyPositionModeChanged(location::EMyPositionMode mode)
{
  if (m_myPositionModeSignal != nullptr)
    m_myPositionModeSignal(mode);
}

bool Framework::CreateDrapeEngine(JNIEnv * env, jobject jSurface, int densityDpi)
{
  m_contextFactory = make_unique_dp<dp::ThreadSafeFactory>(new AndroidOGLContextFactory(env, jSurface));
  AndroidOGLContextFactory const * factory = m_contextFactory->CastFactory<AndroidOGLContextFactory>();
  if (!factory->IsValid())
    return false;

  float visualScale = GetBestDensity(densityDpi);
  ::Framework::DrapeCreationParams p;
  p.m_surfaceWidth = factory->GetWidth();
  p.m_surfaceHeight = factory->GetHeight();
  p.m_visualScale = visualScale;

  /// @TODO (iOS developers) remove this stuff and create real logic for init and layout core widgets
  m_skin.reset(new gui::Skin(gui::ResolveGuiSkinFile("default"), visualScale));
  m_skin->Resize(p.m_surfaceWidth, p.m_surfaceHeight);
  m_skin->ForEach([&p](gui::EWidget widget, gui::Position const & pos)
  {
    p.m_widgetsInitInfo[widget] = pos;
  });

  p.m_widgetsInitInfo[gui::WIDGET_SCALE_LABLE] = gui::Position(dp::LeftBottom);
  m_work.CreateDrapeEngine(make_ref(m_contextFactory), move(p));
  m_work.EnterForeground();
  LoadState();

  m_work.LoadBookmarks();
  m_work.SetMyPositionModeListener(bind(&Framework::MyPositionModeChanged, this, _1));

  return true;
}

void Framework::DeleteDrapeEngine()
{
  SaveState();
  m_work.DestroyDrapeEngine();
}

void Framework::Resize(int w, int h)
{
  m_contextFactory->CastFactory<AndroidOGLContextFactory>()->UpdateSurfaceSize();
  m_work.OnSize(w, h);

  /// @TODO (iOS developers) remove this stuff and create real logic for layout core widgets
  if (m_skin)
  {
    m_skin->Resize(w, h);

    gui::TWidgetsLayoutInfo layout;
    m_skin->ForEach([&layout](gui::EWidget w, gui::Position const & pos)
    {
      layout[w] = pos.m_pixelPivot;
    });

    m_work.SetWidgetLayout(move(layout));
  }
}

void Framework::SetMapStyle(MapStyle mapStyle)
{
  //@TODO UVR
}

Storage & Framework::Storage()
{
  return m_work.Storage();
}

void Framework::ShowCountry(TIndex const & idx, bool zoomToDownloadButton)
{
  m_doLoadState = false;

  if (zoomToDownloadButton)
  {<commit_msg>review fixes<commit_after>#include "Framework.hpp"
#include "MapStorage.hpp"

#include "../opengl/androidoglcontextfactory.hpp"

#include "../core/jni_helper.hpp"

#include "../country/country_helper.hpp"

#include "../platform/Platform.hpp"

#include "map/information_display.hpp"
#include "map/user_mark.hpp"

#include "drape_frontend/visual_params.hpp"
#include "drape_frontend/user_event_stream.hpp"
#include "drape/pointers.hpp"

#include "coding/file_container.hpp"
#include "coding/file_name_utils.hpp"

#include "geometry/angles.hpp"

#include "platform/country_file.hpp"
#include "platform/local_country_file.hpp"
#include "platform/local_country_file_utils.hpp"
#include "platform/location.hpp"
#include "platform/measurement_utils.hpp"
#include "platform/platform.hpp"
#include "platform/preferred_languages.hpp"
#include "platform/settings.hpp"

#include "base/math.hpp"
#include "base/logging.hpp"

android::Framework * g_framework = 0;

using namespace storage;
using platform::CountryFile;
using platform::LocalCountryFile;

namespace
{

::Framework * frm()
{
  return g_framework->NativeFramework();
}

}

namespace android
{

enum MultiTouchAction
{
  MULTITOUCH_UP    =   0x00000001,
  MULTITOUCH_DOWN  =   0x00000002,
  MULTITOUCH_MOVE  =   0x00000003,
  MULTITOUCH_CANCEL =  0x00000004
};

Framework::Framework()
 : m_doLoadState(true)
 , m_lastCompass(0.0)
 , m_currentMode(location::MODE_UNKNOWN_POSITION)
{
  ASSERT_EQUAL ( g_framework, 0, () );
  g_framework = this;
  m_activeMapsConnectionID = m_work.GetCountryTree().GetActiveMapLayout().AddListener(this);
}

Framework::~Framework()
{
  m_work.GetCountryTree().GetActiveMapLayout().RemoveListener(m_activeMapsConnectionID);
}

void Framework::OnLocationError(int errorCode)
{
  m_work.OnLocationError(static_cast<location::TLocationError>(errorCode));
}

void Framework::OnLocationUpdated(location::GpsInfo const & info)
{
  m_work.OnLocationUpdate(info);
}

void Framework::OnCompassUpdated(location::CompassInfo const & info)
{
  static double const COMPASS_THRASHOLD = my::DegToRad(1.0);

  /// @todo Do not emit compass bearing too often while we are passing it through nv-queue.
  /// Need to make more experiments in future.
  if (fabs(ang::GetShortestDistance(m_lastCompass, info.m_bearing)) >= COMPASS_THRASHOLD)
  {
    m_lastCompass = info.m_bearing;
    m_work.OnCompassUpdate(info);
  }
}

void Framework::UpdateCompassSensor(int ind, float * arr)
{
  m_sensors[ind].Next(arr);
}

float Framework::GetBestDensity(int densityDpi)
{
  typedef pair<int, float> P;
  P dens[] = {
      P(120, 0.75f),
      P(160, 1.0f),
      P(240, 1.5f),
      P(320, 2.0f),
      P(480, 3.0f)
  };

  int prevRange = numeric_limits<int>::max();
  int bestRangeIndex = 0;
  for (int i = 0; i < ARRAY_SIZE(dens); i++)
  {
    int currRange = abs(densityDpi - dens[i].first);
    if (currRange <= prevRange)
    {
      // it is better, take index
      bestRangeIndex = i;
      prevRange = currRange;
    }
    else
      break;
  }

  return dens[bestRangeIndex].second;
}

void Framework::MyPositionModeChanged(location::EMyPositionMode mode)
{
  if (m_myPositionModeSignal != nullptr)
    m_myPositionModeSignal(mode);
}

bool Framework::CreateDrapeEngine(JNIEnv * env, jobject jSurface, int densityDpi)
{
  m_contextFactory = make_unique_dp<dp::ThreadSafeFactory>(new AndroidOGLContextFactory(env, jSurface));
  AndroidOGLContextFactory const * factory = m_contextFactory->CastFactory<AndroidOGLContextFactory>();
  if (!factory->IsValid())
    return false;

  float visualScale = GetBestDensity(densityDpi);
  ::Framework::DrapeCreationParams p;
  p.m_surfaceWidth = factory->GetWidth();
  p.m_surfaceHeight = factory->GetHeight();
  p.m_visualScale = visualScale;

  /// @TODO (android developers) remove this stuff and create real logic for init and layout core widgets
  m_skin.reset(new gui::Skin(gui::ResolveGuiSkinFile("default"), visualScale));
  m_skin->Resize(p.m_surfaceWidth, p.m_surfaceHeight);
  m_skin->ForEach([&p](gui::EWidget widget, gui::Position const & pos)
  {
    p.m_widgetsInitInfo[widget] = pos;
  });

  p.m_widgetsInitInfo[gui::WIDGET_SCALE_LABLE] = gui::Position(dp::LeftBottom);
  m_work.CreateDrapeEngine(make_ref(m_contextFactory), move(p));
  m_work.EnterForeground();
  LoadState();

  m_work.LoadBookmarks();
  m_work.SetMyPositionModeListener(bind(&Framework::MyPositionModeChanged, this, _1));

  return true;
}

void Framework::DeleteDrapeEngine()
{
  SaveState();
  m_work.DestroyDrapeEngine();
}

void Framework::Resize(int w, int h)
{
  m_contextFactory->CastFactory<AndroidOGLContextFactory>()->UpdateSurfaceSize();
  m_work.OnSize(w, h);

  /// @TODO (android developers) remove this stuff and create real logic for layout core widgets
  if (m_skin)
  {
    m_skin->Resize(w, h);

    gui::TWidgetsLayoutInfo layout;
    m_skin->ForEach([&layout](gui::EWidget w, gui::Position const & pos)
    {
      layout[w] = pos.m_pixelPivot;
    });

    m_work.SetWidgetLayout(move(layout));
  }
}

void Framework::SetMapStyle(MapStyle mapStyle)
{
  //@TODO UVR
}

Storage & Framework::Storage()
{
  return m_work.Storage();
}

void Framework::ShowCountry(TIndex const & idx, bool zoomToDownloadButton)
{
  m_doLoadState = false;

  if (zoomToDownloadButton)
  {
{'fraction_non_alphanumeric': 0.13170129993358004, 'fraction_numerical': 0.013473764114242339, 'mean_word_length': 5.099537037037037, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 39, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 8, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5386342', 'n_tokens_mistral': 3799, 'n_tokens_neox': 3619, 'n_words': 659}