package no.dusken.barweb.web.kryssing;
import com.google.common.base.Function;
import com.google.common.collect.Collections2;
import no.dusken.barweb.model.BarPerson;
import no.dusken.barweb.model.Transaksjon;
import no.dusken.barweb.model.TransaksjonVare;
import no.dusken.barweb.model.Vare;
import no.dusken.barweb.service.BarPersonService;
import no.dusken.barweb.service.VareService;
import no.dusken.barweb.service.impl.PersonTransaksjonExtendedService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.HttpClientErrorException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static org.apache.commons.lang.StringUtils.defaultIfBlank;
import static org.apache.commons.lang.StringUtils.isNotBlank;
@Controller
@RequestMapping("/krysse")
public class KrysseController {
private final Logger serverlog = LoggerFactory.getLogger("Krysseklientserver");
private final Logger clientlog = LoggerFactory.getLogger("Krysseklient");
@Autowired
private BarPersonService personService;
@Autowired
private VareService vareService;
@Autowired
private PersonTransaksjonExtendedService personTransaksjonExtendedService;
@Value("${clientKrysseLimit:0}")
private Integer clientKrysseLimit;
@Value("${allowSettingCardCode:false}")
private boolean allowSettingCardCode;
@RequestMapping("/home.do")
public String home(){
return "no/dusken/barweb/web/krysse/krysse";
}
@RequestMapping(value = "/log.do", method = RequestMethod.POST)
public HttpEntity log(@RequestBody LogMessage message){
for (String s : message.getMessages()) {
clientlog.info(s);
}
return new ResponseEntity(HttpStatus.OK);
}
@RequestMapping("/user_by_cardcode.do")
public @ResponseBody Map<String, String> getUsernameByCardCode(@RequestParam String cardCode){
BarPerson person = personService.getByCardID(cardCode);
Map<String, String> data = new HashMap<>();
if (person != null) {
serverlog.info("Returning user with cardCode {} to krysseklient", cardCode);
data.put("username", person.getUsername());
data.put("isExternal", String.valueOf(person.isExternal()));
data.put("nameOfUser", person.getFullName());
data.put("money", person.getMoney().toString());
} else {
serverlog.info("Could not find user with cardCode {}", cardCode);
List<BarPerson> all = personService.findAll();
for (BarPerson barPerson : all) {
String cardCodeOrBlank = defaultIfBlank(barPerson.getCardID(), "UNKNOWN");
if(cardCodeOrBlank.contains(cardCode) || cardCode.contains(cardCodeOrBlank)){
serverlog.info("Found match «{}» for code «{}», user «{}»", cardCodeOrBlank, cardCode, barPerson.getUsername());
barPerson.setCardID(cardCode);
personService.saveAndFlush(barPerson);
return getUsernameByCardCode(cardCode);
}
}
throw new HttpClientErrorException(HttpStatus.NOT_FOUND);
}
return data;
}
@RequestMapping(value = "/submit_transaction.do", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE)
public HttpEntity handleSubmit(@RequestBody SubmittedTransaction transaction, HttpServletRequest request){
List<TransaksjonVare> transaksjonVares = getTransaksjonVares(transaction);
serverlog.info("Recieved {}", transaksjonVares);
BarPerson barPerson = personService.getByUsername(transaction.getUsername());
Transaksjon transaksjon = new Transaksjon();
transaksjon.setBarPerson(barPerson);
transaksjon.setExternal(barPerson.isExternal());
transaksjon.setTransaksjoner(transaksjonVares);
transaksjon.setComment("Krysseklient, IP:" + request.getRemoteAddr());
for(TransaksjonVare t : transaksjonVares) t.setTransaksjon(transaksjon);
personTransaksjonExtendedService.doTransactional(barPerson.getId(), transaksjon);
return new ResponseEntity(HttpStatus.CREATED);
}
private List<TransaksjonVare> getTransaksjonVares(SubmittedTransaction transaction) {
Map<Long, TransaksjonVare> registrerteVarer = new HashMap<>();
for(CleanedVare vare : transaction.getBuys()){
TransaksjonVare transaksjonVare = registrerteVarer.get(vare.getId());
if(transaksjonVare == null){
transaksjonVare = new TransaksjonVare();
transaksjonVare.setVare(vareService.getByName(vare.getName()));
transaksjonVare.setAmount(0);
registrerteVarer.put(vare.getId(), transaksjonVare);
}
transaksjonVare.setAmount(transaksjonVare.getAmount() + 1);
}
return new ArrayList<>(registrerteVarer.values());
}
@RequestMapping("/init.do")
public @ResponseBody InitPacket getInitPacket(){
serverlog.info("Sending initpacket.");
List<Vare> varer = vareService.getByActiveTrueOrderByOrderingAsc();
List<CleanedVare> cleanedVares = transform(varer);
return new InitPacket(cleanedVares, clientKrysseLimit, allowSettingCardCode);
}
@RequestMapping("/usersearch.do")
public @ResponseBody List<Map<String, String>> searchUser(@RequestParam String term){
serverlog.info("Searching for user: {}", term);
String t = "%" + term + "%";
List<BarPerson> matchingPersons = personService.findByFirstnameLikeOrSurnameLike(t, t);
return new ArrayList<>(Collections2.transform(matchingPersons, new Function<BarPerson, Map<String, String>>() {
@Override
public Map<String, String> apply(no.dusken.barweb.model.BarPerson person) {
HashMap<String, String> entry = new HashMap<>();
entry.put("label", person.getFullName());
entry.put("value", String.valueOf(person.getId()));
return entry;
}
}));
}
@RequestMapping(value = "/setcardforuser.do", method = RequestMethod.POST)
public ResponseEntity setCardcodeForUser(@RequestBody SetCardcodeCommand setCardcodeCommand){
Long id = setCardcodeCommand.getId();
String cardCode = setCardcodeCommand.getCardCode();
serverlog.info("Trying to set cardcode {} for {}", cardCode, id);
if (isNotBlank(cardCode)) {
BarPerson person = personService.findOne(id);
person.setCardID(cardCode);
personService.saveAndFlush(person);
return new ResponseEntity(HttpStatus.OK);
} else {
return new ResponseEntity(HttpStatus.BAD_REQUEST);
}
}
private List<CleanedVare> transform(List<Vare> varer) {
List<CleanedVare> vareList = new ArrayList<>(varer.size());
for(Vare vare : varer){
vareList.add(new CleanedVare(vare.getId(), vare.getInternalPrice(), vare.getName()));
}
return vareList;
}
@ExceptionHandler(HttpClientErrorException.class)
public void handleIOException(HttpClientErrorException ex, HttpServletResponse response) {
HttpStatus statusCode = ex.getStatusCode();
response.setStatus(statusCode.value());
}
}