// Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "monitor_reconfig/monitor_reconfigure_main.h"

#include <algorithm>
#include <cstdio>
#include <cstdlib>

#include "base/command_line.h"
#include "base/logging.h"
#include "base/string_util.h"

using std::map;
using std::sort;
using std::string;
using std::vector;

namespace monitor_reconfig {

static const char kLcdOutputName[] = "LVDS1";

MonitorReconfigureMain::MonitorReconfigureMain(Display* display,
                                               XRRScreenResources* screen_info)
    : display_(display),
      screen_info_(screen_info),
      lcd_output_(NULL),
      external_output_(NULL) {
  for (int i = 0; i < screen_info_->nmode; ++i) {
    XRRModeInfo* current_mode = &screen_info_->modes[i];
    mode_map_[current_mode->id] = current_mode;
  }
  DetermineOutputs();
}

void MonitorReconfigureMain::Run() {
  vector<ResolutionSelector::Mode> lcd_modes;
  SortModesByResolution(*lcd_output_, &lcd_modes);
  DCHECK(!lcd_modes.empty());

  vector<ResolutionSelector::Mode> external_modes;
  if (IsExternalMonitorConnected()) {
    SortModesByResolution(*external_output_, &external_modes);
    DCHECK(!external_modes.empty());
  }

  ResolutionSelector selector;
  string lcd_resolution, external_resolution, screen_resolution;
  CHECK(selector.FindBestResolutions(lcd_modes,
                                     external_modes,
                                     &lcd_resolution,
                                     &external_resolution,
                                     &screen_resolution));
  CHECK(!lcd_resolution.empty() || !external_resolution.empty());

  // Disable the LCD if we were told to do so (because we're using a higher
  // resolution that'd be clipped on the LCD).
  if (lcd_resolution.empty())
    DisableDevice(lcd_output_->name);

  // If there's no external output connected, disable the device before we try
  // to set the screen resolution; otherwise xrandr will complain if we're
  // trying to set the screen to a smaller size than what the now-unplugged
  // device was using.
  if (external_resolution.empty())
    DisableDevice(external_output_->name);

  // Set the fb to try to avoid the driver's "crtc has no fb" message.
  // Doing this before enabling the display reduces the likelihood of a
  // visible "snap" when returning to the panel.
  SetScreenResolution(screen_resolution);

  // Enable the LCD if appropriate.
  if (!lcd_resolution.empty())
    SetDeviceResolution(lcd_output_->name, lcd_resolution);

  // Enable the external device if appropriate.
  if (!external_resolution.empty())
    SetDeviceResolution(external_output_->name, external_resolution);
}

void MonitorReconfigureMain::DetermineOutputs() {
  CHECK(screen_info_->noutput > 1) << "Expected at least two outputs";
  XRROutputInfo* first_output =
      XRRGetOutputInfo(display_, screen_info_, screen_info_->outputs[0]);
  XRROutputInfo* second_output =
      XRRGetOutputInfo(display_, screen_info_, screen_info_->outputs[1]);

  if (strcmp(first_output->name, kLcdOutputName) == 0) {
    lcd_output_ = first_output;
    external_output_ = second_output;
  } else {
    lcd_output_ = second_output;
    external_output_ = first_output;
  }

  LOG(INFO) << "LCD name: " << lcd_output_->name;
  for (int i = 0; i < lcd_output_->nmode; ++i) {
    XRRModeInfo* mode = mode_map_[lcd_output_->modes[i]];
    LOG(INFO) << "  Mode: " << mode->width << "x" << mode->height;
  }

  LOG(INFO) << "External name: " << external_output_->name;
  for (int i = 0; i < external_output_->nmode; ++i) {
    XRRModeInfo* mode = mode_map_[external_output_->modes[i]];
    LOG(INFO) << "  Mode: " << mode->width << "x" << mode->height;
  }
}

bool MonitorReconfigureMain::IsExternalMonitorConnected() {
  return (external_output_->connection == RR_Connected);
}

void MonitorReconfigureMain::SortModesByResolution(
    const XRROutputInfo& output_info,
    vector<ResolutionSelector::Mode>* modes_out) {
  modes_out->clear();

  for (int i = 0; i < output_info.nmode; ++i) {
    const XRRModeInfo* mode = mode_map_[output_info.modes[i]];
    DCHECK(mode);
    modes_out->push_back(
        ResolutionSelector::Mode(mode->width, mode->height, mode->name));
  }

  sort(modes_out->begin(), modes_out->end(),
       ResolutionSelector::ModeResolutionComparator());
}

bool MonitorReconfigureMain::SetDeviceResolution(
    const std::string& device_name, const std::string& resolution) {
  string command = StringPrintf("xrandr --output %s --mode %s",
                                device_name.c_str(), resolution.c_str());
  LOG(INFO) << "Running " << command.c_str();
  return system(command.c_str()) == 0;
}

bool MonitorReconfigureMain::SetScreenResolution(
    const std::string& resolution) {
  string command = StringPrintf("xrandr --fb %s", resolution.c_str());
  LOG(INFO) << "Running " << command.c_str();
  return system(command.c_str()) == 0;
}

bool MonitorReconfigureMain::DisableDevice(const std::string& device_name) {
  string command = StringPrintf("xrandr --output %s --off",
                                device_name.c_str());
  LOG(INFO) << "Running " << command.c_str();
  return system(command.c_str()) == 0;
}

}  // end namespace monitor_reconfig

int main(int argc, char** argv) {
  CommandLine::Init(argc, argv);
  logging::InitLogging(NULL,
                       logging::LOG_ONLY_TO_SYSTEM_DEBUG_LOG,
                       logging::DONT_LOCK_LOG_FILE,
                       logging::APPEND_TO_OLD_LOG_FILE);
  Display* display = XOpenDisplay(NULL);
  CHECK(display) << "Could not open display";

  Window window = RootWindow(display, DefaultScreen(display));
  XRRScreenResources* screen_info = XRRGetScreenResources(display, window);
  monitor_reconfig::MonitorReconfigureMain main_app(display, screen_info);
  main_app.Run();
  return 0;
}
