/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <android-base/stringprintf.h>
#include <batteryservice/BatteryService.h>
#include <cutils/klog.h>

#include "healthd_draw.h"

#define LOGE(x...) KLOG_ERROR("charger", x);
#define LOGV(x...) KLOG_DEBUG("charger", x);

HealthdDraw::HealthdDraw(animation* anim)
  : kSplitScreen(HEALTHD_DRAW_SPLIT_SCREEN),
    kSplitOffset(HEALTHD_DRAW_SPLIT_OFFSET) {
  gr_init();
  gr_font_size(gr_sys_font(), &char_width_, &char_height_);

  screen_width_ = gr_fb_width() / (kSplitScreen ? 2 : 1);
  screen_height_ = gr_fb_height();

  int res;
  if (!anim->text_clock.font_file.empty() &&
      (res = gr_init_font(anim->text_clock.font_file.c_str(),
                          &anim->text_clock.font)) < 0) {
    LOGE("Could not load time font (%d)\n", res);
  }
  if (!anim->text_percent.font_file.empty() &&
      (res = gr_init_font(anim->text_percent.font_file.c_str(),
                          &anim->text_percent.font)) < 0) {
    LOGE("Could not load percent font (%d)\n", res);
  }
}

HealthdDraw::~HealthdDraw() {}

void HealthdDraw::redraw_screen(const animation* batt_anim, GRSurface* surf_unknown) {
  clear_screen();

  /* try to display *something* */
  if (batt_anim->cur_level < 0 || batt_anim->num_frames == 0)
    draw_unknown(surf_unknown);
  else
    draw_battery(batt_anim);
  gr_flip();
}

void HealthdDraw::blank_screen(bool blank) { gr_fb_blank(blank); }

void HealthdDraw::clear_screen(void) {
  gr_color(0, 0, 0, 255);
  gr_clear();
}

int HealthdDraw::draw_surface_centered(GRSurface* surface) {
  int w = gr_get_width(surface);
  int h = gr_get_height(surface);
  int x = (screen_width_ - w) / 2 + kSplitOffset;
  int y = (screen_height_ - h) / 2;

  LOGV("drawing surface %dx%d+%d+%d\n", w, h, x, y);
  gr_blit(surface, 0, 0, w, h, x, y);
  if (kSplitScreen) {
    x += screen_width_ - 2 * kSplitOffset;
    LOGV("drawing surface %dx%d+%d+%d\n", w, h, x, y);
    gr_blit(surface, 0, 0, w, h, x, y);
  }

  return y + h;
}

int HealthdDraw::draw_text(const GRFont* font, int x, int y, const char* str) {
  int str_len_px = gr_measure(font, str);

  if (x < 0) x = (screen_width_ - str_len_px) / 2;
  if (y < 0) y = (screen_height_ - char_height_) / 2;
  gr_text(font, x + kSplitOffset, y, str, false /* bold */);
  if (kSplitScreen)
    gr_text(font, x - kSplitOffset + screen_width_, y, str, false /* bold */);

  return y + char_height_;
}

void HealthdDraw::determine_xy(const animation::text_field& field,
                               const int length, int* x, int* y) {
  *x = field.pos_x;

  int str_len_px = length * field.font->char_width;
  if (field.pos_x == CENTER_VAL) {
    *x = (screen_width_ - str_len_px) / 2;
  } else if (field.pos_x >= 0) {
    *x = field.pos_x;
  } else {  // position from max edge
    *x = screen_width_ + field.pos_x - str_len_px - kSplitOffset;
  }

  *y = field.pos_y;

  if (field.pos_y == CENTER_VAL) {
    *y = (screen_height_ - field.font->char_height) / 2;
  } else if (field.pos_y >= 0) {
    *y = field.pos_y;
  } else {  // position from max edge
    *y = screen_height_ + field.pos_y - field.font->char_height;
  }
}

void HealthdDraw::draw_clock(const animation* anim) {
  static constexpr char CLOCK_FORMAT[] = "%H:%M";
  static constexpr int CLOCK_LENGTH = 6;

  const animation::text_field& field = anim->text_clock;

  if (field.font == nullptr || field.font->char_width == 0 ||
      field.font->char_height == 0)
    return;

  time_t rawtime;
  time(&rawtime);
  tm* time_info = localtime(&rawtime);

  char clock_str[CLOCK_LENGTH];
  size_t length = strftime(clock_str, CLOCK_LENGTH, CLOCK_FORMAT, time_info);
  if (length != CLOCK_LENGTH - 1) {
    LOGE("Could not format time\n");
    return;
  }

  int x, y;
  determine_xy(field, length, &x, &y);

  LOGV("drawing clock %s %d %d\n", clock_str, x, y);
  gr_color(field.color_r, field.color_g, field.color_b, field.color_a);
  draw_text(field.font, x, y, clock_str);
}

void HealthdDraw::draw_percent(const animation* anim) {
  int cur_level = anim->cur_level;
  if (anim->cur_status == BATTERY_STATUS_FULL) {
    cur_level = 100;
  }

  if (cur_level <= 0) return;

  const animation::text_field& field = anim->text_percent;
  if (field.font == nullptr || field.font->char_width == 0 ||
      field.font->char_height == 0) {
    return;
  }

  std::string str = base::StringPrintf("%d%%", cur_level);

  int x, y;
  determine_xy(field, str.size(), &x, &y);

  LOGV("drawing percent %s %d %d\n", str.c_str(), x, y);
  gr_color(field.color_r, field.color_g, field.color_b, field.color_a);
  draw_text(field.font, x, y, str.c_str());
}

void HealthdDraw::draw_battery(const animation* anim) {
  const animation::frame& frame = anim->frames[anim->cur_frame];

  if (anim->num_frames != 0) {
    draw_surface_centered(frame.surface);
    LOGV("drawing frame #%d min_cap=%d time=%d\n", anim->cur_frame,
         frame.min_level, frame.disp_time);
  }
  draw_clock(anim);
  draw_percent(anim);
}

void HealthdDraw::draw_unknown(GRSurface* surf_unknown) {
  int y;
  if (surf_unknown) {
    draw_surface_centered(surf_unknown);
  } else {
    gr_color(0xa4, 0xc6, 0x39, 255);
    y = draw_text(gr_sys_font(), -1, -1, "Charging!");
    draw_text(gr_sys_font(), -1, y + 25, "?\?/100");
  }
}
