package org.ironbrain;
import com.google.common.base.Joiner;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.mutable.Mutable;
import org.apache.commons.lang3.mutable.MutableObject;
import org.apache.commons.lang3.tuple.Pair;
import org.ironbrain.core.*;
import org.ironbrain.dao.AllDao;
import org.ironbrain.utils.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
@SessionAttributes({APIController.USER})
public class APIController extends AllDao {
public static final String USER = "user";
@Autowired
protected SessionData data;
protected User getUser() {
return data.getUser();
}
@ResponseBody
@RequestMapping(method = RequestMethod.GET, value = "/get_sections")
public List<Section> getSections(@RequestParam int sec) {
return sectionDao.getChildren(sec, getUser());
}
@ResponseBody
@RequestMapping(method = RequestMethod.GET, value = "/get_section")
public Section getSection(@RequestParam int sec) {
return sectionDao.getSection(sec, getUser());
}
@ResponseBody
@RequestMapping(method = RequestMethod.GET, value = "/get_section_from_ticket")
public Section getSectionFromTicket(@RequestParam int ticketId) {
return sectionDao.getSectionFromTicket(ticketId);
}
@ResponseBody
@RequestMapping(method = RequestMethod.GET, value = "/get_path")
public List<Section> getPath(@RequestParam int sec) {
return sectionDao.getPath(sec);
}
@ResponseBody
@RequestMapping(method = RequestMethod.GET, value = "/add_section")
public Result addSection(@RequestParam String label, Integer parent) {
return sectionDao.addSection(parent, label, getUser());
}
@ResponseBody
@RequestMapping(method = RequestMethod.GET, value = "/delete_section")
public Result deleteSection(@RequestParam int id) {
return sectionDao.deleteSection(id);
}
@ResponseBody
@RequestMapping(method = RequestMethod.GET, value = "/get_ticket")
public Ticket getTicket(@RequestParam int id) {
return ticketDao.getTicket(id);
}
@ResponseBody
@RequestMapping(method = RequestMethod.GET, value = "/get_ticket_label")
public String getTicketLabel(@RequestParam int id) {
return ticketDao.getTicketLabel(id);
}
@ResponseBody
@RequestMapping(method = RequestMethod.POST, value = "/update_ticket")
public Result updateTicket(@RequestParam int id, @RequestParam String answers,
@RequestParam String questions, @RequestParam String label,
@RequestParam String customInfo,
@RequestParam long clientVersionDate) {
return ticketDao.updateTicket(id, answers, questions, customInfo, label, clientVersionDate);
}
@ResponseBody
@RequestMapping(method = RequestMethod.GET, value = "/check_ticket")
public Result checkTicket(@RequestParam int id, @RequestParam long clientVersionDate) {
return ticketDao.checkTicket(id, clientVersionDate);
}
@RequestMapping(method = RequestMethod.GET, value = "/update_ticket_edit_date")
public void updateTicketEditDate(@RequestParam int id, @RequestParam long editDate) {
ticketDao.updateTicket(id, editDate);
}
@ResponseBody
@RequestMapping(method = RequestMethod.GET, value = "/add_ticket")
public Section addTicket(@RequestParam int section) {
return ticketDao.addTicket(section, getUser()).getLeft();
}
@ResponseBody
@RequestMapping(method = RequestMethod.GET, value = "/get_child_count")
public Long getChildCount(@RequestParam int section) {
return sectionDao.getChildCount(section);
}
@RequestMapping(method = RequestMethod.GET, value = "/login")
@ResponseBody
public Result login(@RequestParam String login, @RequestParam String password) {
User user = userDao.getUserByLogin(login);
if (user == null) {
return Result.getError("Нет такого пользователя!");
}
if (user.getPassword().equals(password)) {
data.setUser(user);
return Result.getOk();
} else {
return Result.getError("Неверный пароль!");
}
}
@RequestMapping(method = RequestMethod.GET, value = "/logout")
public String logout() {
data.setUser(null);
return "redirect:/.";
}
@ResponseBody
@RequestMapping(method = RequestMethod.GET, value = "/add_remind")
public String addRemind(Integer section, Integer ticket) {
if (section != null) {
remindDao.addRemind(section, getUser().getId());
}
if (ticket != null) {
remindDao.addRemindTicket(ticket);
}
return "OK";
}
@ResponseBody
@RequestMapping(method = RequestMethod.GET, value = "/get_reminds")
public List<Remind> getReminds() {
return remindDao.getReminds(getUser());
}
@ResponseBody
@RequestMapping(method = RequestMethod.GET, value = "/delete_remind")
public Result deleteRemind(@RequestParam int id) {
return remindDao.delete(id);
}
@ResponseBody
@RequestMapping(method = RequestMethod.GET, value = "/remind")
public Result remind(@RequestParam String ids) {
List<Remind> reminds = new ArrayList<>();
String[] idArray = ids.split(",");
for (String idStr : idArray) {
int id = new Integer(idStr);
reminds.add(remindDao.get(id));
}
Exam exam = examDao.create(reminds.size());
i = 1;
reminds.forEach(remind -> {
Ticket ticket = ticketDao.getTicket(remind.getTicket());
Try someTry = tryDao.create(ticket, exam.getId(), i++, 1);
});
return Result.getOk();
}
@ResponseBody
@RequestMapping(method = RequestMethod.GET, value = "/get_last_undone_exam")
public Exam getLastUndoneExam() {
return examDao.getLastUndoneExam();
}
@ResponseBody
@RequestMapping(method = RequestMethod.GET, value = "/get_tries_from_exam")
public List<Try> getTriesFromExam(int id) {
return tryDao.getTriesFromExam(id);
}
@ResponseBody
@RequestMapping(method = RequestMethod.GET, value = "/get_temp_try")
public Try getTempTry(int id) {
return tryDao.getTempTry(id);
}
@ResponseBody
@RequestMapping(method = RequestMethod.GET, value = "/try_done")
public Result tryDone(@RequestParam int id, @RequestParam boolean correct, @RequestParam String remindTo) {
Try someTry = tryDao.getTry(id);
someTry.setEndMs(IB.getNowMs());
someTry.setRemindState(remindTo);
someTry.setRemindTo(Ticket.getMsFromState(remindTo));
if (!remindTo.equals(Ticket.REMIND_NOW)) {
Section tSection = sectionDao.getSectionFromTicket(someTry.getTicket());
tSection.setRemind(Ticket.getMsFromState(remindTo));
sectionDao.update(tSection);
}
if (correct) {
someTry.setCorrect(true);
}
someTry.setDone(true);
tryDao.updateTry(someTry);
return Result.getOk();
}
int i;
@RequestMapping(method = RequestMethod.GET, value = "/to_next_attempt")
public void toNextAttempt() {
Exam lastExam = getLastUndoneExam();
List<Try> tries = getTriesFromExam(lastExam.getId());
Try lastTry = tries.get(tries.size() - 1);
i = 0;
int lastAttemptNum = lastTry.getAttemptNum();
tries.forEach(someTry -> {
if ((!someTry.getCorrect()) && (someTry.getAttemptNum() == lastAttemptNum)) {
Try newTry = tryDao.createNextAttempt(someTry, ++i);
}
});
lastExam.setCount(i);
examDao.update(lastExam);
}
@ResponseBody
@RequestMapping(method = RequestMethod.GET, value = "/query")
public List<Ticket> query(@RequestParam String query) {
return ticketDao.query(query);
}
@ResponseBody
@RequestMapping(method = RequestMethod.GET, value = "/update_all_paths")
public String updateAllPath() {
List<Ticket> tickets = ticketDao.getAllTickets();
StringBuilder res = new StringBuilder();
tickets.forEach(ticket -> {
Section section = sectionDao.getSectionFromTicket(ticket.getId());
if (section != null) {
String pathString = getPathToSection(section.getId());
res.append(pathString);
ticket.setPath(pathString);
ticketDao.updateTicket(ticket);
}
});
return res.toString();
}
public String getPathToSection(int sectionId) {
List<String> path = getPath(sectionId)
.stream()
.map(Section::getLabel)
.collect(Collectors.toList());
String pathString = Joiner.on("→").join(path);
return pathString;
}
@ResponseBody
@RequestMapping(method = RequestMethod.GET, value = "/add_field")
public Result addField(@RequestParam String name) {
return fieldDao.addField(name);
}
@ResponseBody
@RequestMapping(method = RequestMethod.GET, value = "/get_fields")
public List<Field> getFields() {
return fieldDao.getFields();
}
@ResponseBody
@RequestMapping(method = RequestMethod.GET, value = "/add_field_to_section")
public Result<Integer> addFieldToSection(@RequestParam Integer fieldId, @RequestParam Integer targetId) {
SectionToField sectionToField = fieldDao.addFieldToSection(fieldId, targetId);
return Result.getOk(sectionToField.getId());
}
@ResponseBody
@RequestMapping(method = RequestMethod.GET, value = "/invert_section_to_field")
public Result invertField(@RequestParam Integer id) {
return secToFDao.invertField(id);
}
@ResponseBody
@RequestMapping(method = RequestMethod.GET, value = "/delete_section_to_field")
public Result deleteSectionToField(@RequestParam Integer id) {
return secToFDao.deleteSectionToField(id);
}
@ResponseBody
@RequestMapping(method = RequestMethod.GET, value = "/add_field_to_direction")
public Result addFieldToDirection(@RequestParam Integer fieldId, @RequestParam Integer targetId) {
return fieldDao.addFieldToDirection(fieldId, targetId);
}
@ResponseBody
@RequestMapping(method = RequestMethod.GET, value = "/delete_direction_to_field")
public Result deleteDirectionToField(@RequestParam Integer id) {
return dirToFDao.deleteDirectionToField(id);
}
@ResponseBody
@RequestMapping(method = RequestMethod.GET, value = "/add_direction")
public Result addDirection(@RequestParam String name) {
Direction direction = directionDao.addDirection(name);
return Result.getOk(direction.getId());
}
@ResponseBody
@RequestMapping(method = RequestMethod.GET, value = "/recalculate_direction")
public Result recalculateDirection(@RequestParam Integer id) {
return directionDao.recalculateDirection(id);
}
@ResponseBody
@RequestMapping(method = RequestMethod.GET, value = "/register_user")
public Result registerUser(@RequestParam String login, @RequestParam String password,
@RequestParam String email, @RequestParam Boolean extended) {
return userDao.registerUser(login, password, email, extended);
}
public Pair<Section, Ticket> addTicketToTime() {
Section timeSection = sectionDao.getTimeSection();
LocalDate date = LocalDate.now();
String nowYearStr = Integer.toString(date.getYear());
Section sectionNowYear = ensureChildSectionExist(timeSection.getId(), nowYearStr);
String nowMonthStr = String.format("%d", date.getMonthValue());
Section sectionNowMonth = ensureChildSectionExist(sectionNowYear.getId(), nowMonthStr);
String nowDayStr = String.format("%d", date.getDayOfMonth());
Section sectionNowDay = ensureChildSectionExist(sectionNowMonth.getId(), nowDayStr);
return ticketDao.addTicket(sectionNowDay.getId());
}
@RequestMapping(method = RequestMethod.GET, value = "/add_ticket_to_time")
public String addTicketToTimeAndRedirect() {
return "redirect:/edit_ticket?id=" + addTicketToTime().getLeft().getTicket();
}
@RequestMapping(method = RequestMethod.GET, value = "/slice_and_remind")
public String sliceAndRemind(@RequestParam int directionId, int count) {
Direction direction = directionDao.getDirection(directionId);
directionDao.sliceAndAddToRemind(direction, count);
return "redirect:/exam";
}
private Section ensureChildSectionExist(int parent, String name) {
List<Section> sections = sectionDao.getChildren(parent);
Mutable<Section> childrenMut = new MutableObject<>();
sections.forEach(section -> {
if (section.getLabel().equals(name)) {
childrenMut.setValue(section);
}
});
Section child = childrenMut.getValue();
if (child == null) {
child = sectionDao.addSection(parent, name).getData();
}
return child;
}
@RequestMapping(method = RequestMethod.GET, value = "/update_section")
@ResponseBody
public Result updateSection(@RequestParam int id, String label, Integer parent) {
Section section = sectionDao.getSection(id);
if (label != null) {
section.setLabel(label);
}
if (parent != null) {
section.setParent(parent);
}
sectionDao.update(section);
return Result.getOk();
}
@RequestMapping(method = RequestMethod.GET, value = "/cut_section")
@ResponseBody
public Result cutSection(@RequestParam Integer id) {
data.setBufferSectionId(id);
return Result.getOk();
}
@RequestMapping(method = RequestMethod.GET, value = "/paste_section")
@ResponseBody
public Result pastSection(@RequestParam Integer parent) {
Section section = sectionDao.getSection(data.getBufferSectionId());
List<Section> parentPath = sectionDao.getPath(parent);
if (parentPath.contains(section)) {
return Result.getError("Рекурсивное добавление!");
}
section.setParent(parent);
sectionDao.update(section);
data.setBufferSectionId(null);
return Result.getOk();
}
@RequestMapping(method = RequestMethod.POST, value = "/upload_file")
@ResponseBody
public Result uploadFileHandler(@RequestParam MultipartFile file) {
String extension = FilenameUtils.getExtension(file.getOriginalFilename());
try {
File userHomeDir = data.getHomeDir();
File userFilesDir = new File(userHomeDir, User.FILES_DIR);
File userCommonsFir = new File(userFilesDir, User.COMMONS_DIR);
File thisFile = new File(userCommonsFir, DateUtils.getUniqueFileName() + "." + extension);
FileUtils.copyInputStreamToFile(file.getInputStream(), thisFile);
Path basePath = data.getFilesDir().toPath();
Path relPath = basePath.relativize(thisFile.toPath());
String relPathStr = MainController.USER_URL + File.separator + relPath.toString();
String relPathStrUni = FilenameUtils.separatorsToUnix(relPathStr);
return Result.getOk(relPathStrUni);
} catch (IOException e) {
e.printStackTrace();
return Result.getError(e.getMessage());
}
}
@RequestMapping(method = RequestMethod.GET, value = "/update_profile")
@ResponseBody
public Result updateProfile(String newPassword, String newPasswordConfirm, Boolean extendedProfile, String port, String email) {
return userDao.updateProfile(newPassword, newPasswordConfirm, extendedProfile, port, email);
}
}