package de.onyxbits.tradetrax.pages;
import java.text.DateFormat;
import java.text.ParseException;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import org.apache.tapestry5.Block;
import org.apache.tapestry5.annotations.*;
import org.apache.tapestry5.beaneditor.BeanModel;
import org.apache.tapestry5.beaneditor.Validate;
import org.apache.tapestry5.corelib.components.DateField;
import org.apache.tapestry5.corelib.components.Form;
import org.apache.tapestry5.corelib.components.Grid;
import org.apache.tapestry5.corelib.components.Select;
import org.apache.tapestry5.corelib.components.Submit;
import org.apache.tapestry5.corelib.components.TextField;
import org.apache.tapestry5.corelib.components.Zone;
import org.apache.tapestry5.hibernate.annotations.CommitAfter;
import org.apache.tapestry5.ioc.Messages;
import org.apache.tapestry5.ioc.annotations.*;
import org.apache.tapestry5.services.BeanModelSource;
import org.apache.tapestry5.services.javascript.JavaScriptSupport;
import org.hibernate.Session;
import de.onyxbits.tradetrax.components.Layout;
import de.onyxbits.tradetrax.entities.IdentUtil;
import de.onyxbits.tradetrax.entities.Stock;
import de.onyxbits.tradetrax.remix.AcquisitionFields;
import de.onyxbits.tradetrax.remix.LedgerColumns;
import de.onyxbits.tradetrax.remix.StockPagedGridDataSource;
import de.onyxbits.tradetrax.remix.StockState;
import de.onyxbits.tradetrax.remix.TimeSpan;
import de.onyxbits.tradetrax.services.EventLogger;
import de.onyxbits.tradetrax.services.MoneyRepresentation;
import de.onyxbits.tradetrax.services.SettingsStore;
/**
* Start page of application tradetracker.
*/
@Import(library = "context:js/mousetrap.min.js")
public class Index {
@SessionAttribute(Layout.FOCUSID)
private long focusedStockId;
@Property
private DateFormat dateFormat = DateFormat.getDateInstance(DateFormat.MEDIUM);
@Inject
private Session session;
@Inject
private Messages messages;
@Inject
private BeanModelSource ledgerSource;
@Property
@Validate("required,minlength=3")
private String buyName;
@Property
private String buyVariant;
@Property
private String buyCost;
@Property
private String buyReturns;
@Property
private String buyLocation;
@Property
private int buyAmount = 1;
@Property
private StockPagedGridDataSource stocks;
@Property
private Stock row;
@Component(id = "buyform")
private Form buyForm;
@Component(id = "buyName")
private TextField buyNameField;
@Component(id = "buyVariant")
private TextField buyVariantField;
@Component(id = "buyAmount")
private TextField buyAmountField;
@Component(id = "buyCost")
private TextField buyCostField;
@Component(id = "buyReturns")
private TextField buyReturnsField;
@Component(id = "buyLocation")
private TextField buyLocationFiels;
@Component(id = "ledger")
private Grid ledger;
@Component(id = "filterForm")
private Form filterForm;
@Component(id = "reset")
private Submit reset;
@Persist
@Property
private String filterName;
@Persist
@Property
private String filterLocation;
@Component(id = "filterLocation")
private TextField filterLocationField;
@Persist
@Property
private String filterComment;
@Component(id = "filterComment")
private TextField filterCommentField;
@Component(id = "filterName")
private TextField filterNameField;
@Persist
@Property
private String filterVariant;
@Component(id = "filterVariant")
private TextField filterVariantField;
@Persist
@Property
private StockState filterState;
@Component(id = "filterState")
private Select filterStateField;
@Persist
@Property
private Date filterAcquisition;
@Component(id = "filterAcquisition")
private DateField filterAcquisitionField;
@Persist
@Validate("required")
@Property
private TimeSpan filterAcquisitionSpan;
@Component(id = "filterAcquisitionSpan")
private Select filterAcquisitionSpanField;
@Persist
@Property
private Date filterLiquidation;
@Component(id = "filterLiquidation")
private DateField filterLiquidationField;
@Persist
@Validate("required")
@Property
private TimeSpan filterLiquidationSpan;
@Component(id = "filterLiquidationSpan")
private Select filterLiquidationSpanField;
@Inject
private SettingsStore settingsStore;
@Inject
private EventLogger eventLogger;
@Inject
private MoneyRepresentation moneyRepresentation;
@Property
private String matches;
@Inject
private Block acquisitionblock;
@Inject
private Block filterblock;
@InjectComponent
private Zone flipview;
@Property
@Persist
private boolean showFilterForm;
@Property
private long matchingItemCount;
@Property
@Persist
private boolean autofocusBuyForm;
@Property
private int matchingAssetCount;
@Inject
private JavaScriptSupport javaScriptSupport;
public String styleFor(String tag) {
String tmp = settingsStore.get(SettingsStore.TCACFIELDS, AcquisitionFields.DEFAULT);
if (!tmp.contains(tag)) {
return "display:none;";
}
return "";
}
public Block getActiveForm() {
if (showFilterForm) {
return filterblock;
}
else {
return acquisitionblock;
}
}
public void setupRender() {
stocks = new StockPagedGridDataSource(session).withName(filterName).withVariant(filterVariant)
.withState(filterState).withLocation(filterLocation).withComment(filterComment)
.withAcquisition(filterAcquisition, filterAcquisitionSpan)
.withLiquidation(filterLiquidation, filterLiquidationSpan);
matchingAssetCount = stocks.getAvailableRows();
matchingItemCount = stocks.getItemCount();
}
public void afterRender() {
autofocusBuyForm = false;
// Let the Escape key toggle the forms. It is slightly messy to do it this
// way. Using getElementById() would be preferable, but the id is assigned
// dynamically.
javaScriptSupport
.addScript("Mousetrap.prototype.stopCallback = function(e, element) {return false;};");
javaScriptSupport
.addScript("Mousetrap.bind('esc', function() {document.getElementsByClassName('formtoggler')[0].click();});");
}
public BeanModel<Object> getLedgerModel() {
BeanModel<Object> model = ledgerSource.createDisplayModel(Object.class, messages);
List<LedgerColumns> tmp = LedgerColumns.fromCsv(settingsStore.get(SettingsStore.TCLCOLUMNS,
LedgerColumns.DEFAULT));
for (LedgerColumns col : tmp) {
model.addEmpty(col.getName()).sortable(
LedgerColumns.BUYPRICE.getName().equals(col.getName())
|| LedgerColumns.SELLPRICE.getName().equals(col.getName())
|| LedgerColumns.LIQUIDATED.getName().equals(col.getName())
|| LedgerColumns.ACQUIRED.getName().equals(col.getName()));
}
return model;
}
public List<String> onProvideCompletionsFromBuyVariant(String partial) {
return IdentUtil.suggestVariants(session, partial);
}
public List<String> onProvideCompletionsFromBuyName(String partial) {
return IdentUtil.suggestNames(session, partial);
}
public void onValidateFromBuyForm() {
try {
moneyRepresentation.userToDatabase(buyCost, 1);
}
catch (ParseException e) {
buyForm.recordError(buyCostField, messages.get("invalid-numberformat"));
}
try {
moneyRepresentation.userToDatabase(buyReturns, 1);
}
catch (ParseException e) {
buyForm.recordError(buyReturnsField, messages.get("invalid-numberformat"));
}
}
public Object onToggleForm() {
showFilterForm = !showFilterForm;
return flipview;
}
@CommitAfter
public Object onSuccessFromBuyForm() {
Stock item = new Stock();
item.setName(IdentUtil.findName(session, buyName));
item.setVariant(IdentUtil.findVariant(session, buyVariant));
try {
item.setBuyPrice(moneyRepresentation.userToDatabase(buyCost, 1));
item.setSellPrice(moneyRepresentation.userToDatabase(buyReturns, 1));
}
catch (ParseException e) {
// We already validated this
}
Calendar now = Calendar.getInstance();
now.set(Calendar.MILLISECOND, 0);
now.set(Calendar.SECOND, 0);
now.set(Calendar.MINUTE, 0);
now.set(Calendar.HOUR_OF_DAY, 0);
item.setLocation(buyLocation);
item.setUnitCount(buyAmount);
item.setAcquired(now.getTime());
session.persist(item);
focusedStockId = item.getId();
eventLogger.acquired(item);
withNoFilters();
ledger.reset();
autofocusBuyForm = true;
return Index.class;
}
public void onSelectedFromReset() {
// Reset button event -> return all values to their defaults...
filterName = null;
filterState = null;
filterVariant = null;
filterAcquisition = null;
filterLiquidation = null;
filterLocation = null;
filterComment = null;
ledger.reset();
// ... then just fall through to the success action.
}
public Object onSuccessFromFilterForm() {
return Index.class;
}
public Index withNoFilters() {
filterName = null;
filterState = null;
filterVariant = null;
filterAcquisition = null;
filterLiquidation = null;
filterLocation = null;
filterComment = null;
showFilterForm = false;
return this;
}
public Index withFilterName(String name) {
this.filterName = name;
showFilterForm = true;
return this;
}
public Index withFilterVariant(String name) {
this.filterVariant = name;
showFilterForm = true;
return this;
}
public String hasFilterName() {
return filterName;
}
public String hasFilterVariant() {
return filterVariant;
}
}