text:
#import "mCatalogue.h"
#import "TBXML.h"
#import <QuartzCore/QuartzCore.h>
#import "functionLibrary.h"

#import "NSString+colorizer.h"
#import "UIImageView+WebCache.h"
#import "SDImageCache.h"

//#import "NRGridView.h"
//#import "customgridcell.h"
#import "NSString+size.h"
#import "NSString+html.h"

#import "mCatalogueParameters.h"
#import "mCatalogueCategory.h"
#import "mCatalogueItem.h"
#import "mCatalogueItemVC.h"
//#import "gradientselection.h"

#import "mCatalogueDBManager.h"

#import "mCatalogueEntryView.h"
#import "mCatalogueItemView.h"
#import "mCatalogueCategoryView.h"

#import "mCatalogueEntry.h"
#import "mCatalogueGridCell.h"
#import "mCatalogueRowCell.h"

//#import "navigationcontroller.h"
//#import "labelwidget.h"

//#import "reachability.h"

//#import "IBPCart.h"//"IBPayments/IBPCart.h"
//#import "IBPCartItem.h"//"IBPayments/IBPCartItem.h"
#import "IBPPayPalManager.h"//"IBPayments/IBPPayPalManager.h"
//#import "iphmainviewcontroller.h"

//#import "IBSideBarModuleAction.h"//"IBSideBar/IBSideBarModuleAction.h"

/*
 * Beware of big xml configs (several Mbs) causing app crashes.
 * So parse xml with categories and and flush its contents to db.
 *
 * Here goes constants for batch size of items and categories, eligible to flush to db
 */
#define kCatalogueItemBatchCapacity 1000
#define kCatalogueCategoryBatchCapacity 1000

#define kCatalogueTableRowGap_Grid 8.0f

#define kCatalogueTableColumnMarginRigth kCatalogueTableColumnMarginLeft

#define kCatalogueTableColumnGap_Row 0.0f // only one column, no gaps

#define kCatalogueTable_PaddingHorizontal_Grid 6.0f

#define kCatalogueAssortmentCategoriesKey @"categories"
#define kCatalogueAssortmentItemsKey @"items"

#define kCatalogueImagelessCategoryCellBackground [[UIColor blackColor] colorWithAlphaComponent:0.2f]

#define kCatalogueNoResultsFoundLabelLeftMargin 20.0f
#define kCatalogueNoResultsFoundLabelOriginY    120.0f
#define kCatalogueNoResultsFoundLabelHeight     25.0f

#define kCatalogueInitialControllerIndexInStack 1
#define kCatalogueStackSizeOnInitialController  2

#define kCatalogueItemBackgroundColor [UIColor whiteColor]

#define kCatalogueMaskViewTag 10003

#define kCatalogueParsedParametersKey @"kCatalogueParsedParametersKey"

mCatalogueDBManager *catalogueDBManager = nil;

typedef struct{
  mCatalogueEntry *first;
  mCatalogueEntry *second;
} mCatalogueEntryPair;

@interface mCatalogueViewController(){
  UIStatusBarStyle initialStatusBarStyle;
  /**
   * Determines if this controller is the first one
   * after user opens the widget
   */
  BOOL isFirstPage;

  BOOL itemViewsShoulShowPlaceholder;
}

@property(nonatomic, strong) NSMutableDictionary *assortment;
@property(nonatomic, strong) UITableView *catalogueTableView;
@property(nonatomic, assign) int elementIndex;

@end

@implementation mCatalogueViewController{
  NSInteger categoriesCount;
  NSInteger itemsCount;

  UITapGestureRecognizer *cancelSearchGestureRecognizer;

  auth_Share *aSha;
}

#pragma mark -

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
  self = [super initWithNavBarAppearance:mCatalogueSearchBarViewDefaultAppearance];

  if ( self )
    {
    self.assortment = [NSMutableDictionary dictionary];

    _categoryToShow = 0;
    _searchToken = nil;
    _inSearchMode = NO;

    _tabBarIsHidden = NO;
    _showTabBar = YES;

    itemViewsShoulShowPlaceholder = NO;

    aSha = [[auth_Share alloc] init];
    }
  return self;
}

- (void)dealloc
{
  self.catalogueTableView = nil;
  self.assortment = nil;

  if(aSha){
    aSha.delegate = nil;
    aSha.viewController = nil;

    [aSha release];
    aSha = nil;
  }

  [super dealloc];
}

#pragma mark - XML parsing
/**
 *  Special parser for processing original xml file
 *
 *  @param xmlElement_ XML node
 *  @param params_     Dictionary with module parameters
 */
+ (void)parseXML:(NSValue *)xmlElement_
      withParams:(NSMutableDictionary *)params_
{

//  NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
//  [request setHTTPMethod:@"GET"];
//  [request setURL:[NSURL URLWithString:@"http://ibuilder.solovathost.com/test/data.catalog.xml"]];
//
//  NSError *error = [[NSError alloc] init];
//  NSHTTPURLResponse *responseCode = nil;
//
//  NSData *oResponseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&responseCode error:&error];
//
//  if([responseCode statusCode] != 200){
//    NSLog(@"Error getting, HTTP status code %li", (long)[responseCode statusCode]);
//  }
//  NSString *s = [[NSString alloc] initWithData:oResponseData encoding:NSUTF8StringEncoding];
//  NSLog(@"fuckin log %@", s);
//
//
//  NSData *dat = [s dataUsingEncoding:NSUTF8StringEncoding];
//  TBXML *tbxml = [[TBXML newTBXMLWithXMLData:dat
//                                       error:nil ] autorelease];
//
//  TBXMLElement element;
//  element = *[tbxml rootXMLElement];
//
//
//  TBXMLElement *configElement = [TBXML childElementNamed:@"config" parentElement:&element];
//
//
//  NSMutableDictionary *catalogueParsedParameters = [NSMutableDictionary dictionary];
//
//  [self parseParamsFromElement:configElement
//                intoParameters:catalogueParsedParameters];
//
//  [self parseColorskinFromElement:configElement
//                   intoParameters:catalogueParsedParameters];
//
//  [self parsePaymentDataFromElement:&element
//                     intoParameters:catalogueParsedParameters];
//
//  [self parseShoppingCartOptionsFromElement:configElement
//                             intoParameters:catalogueParsedParameters];
//
//
//  [params_ setObject:catalogueParsedParameters forKey:kCatalogueParsedParametersKey];
//
//  BOOL dbIsReady = [self prepareDatabaseAtPath:[mCatalogueParameters dbFilePath:[params_ objectForKey:@"module_id"]]];
//
//  if(dbIsReady){
//    [self persistCatalogueContents:element];
//  }

  TBXMLElement element;
  [xmlElement_ getValue:&element];

  TBXMLElement *configElement = [TBXML childElementNamed:@"config" parentElement:&element];

  NSMutableDictionary *catalogueParsedParameters = [NSMutableDictionary dictionary];

  [self parseParamsFromElement:configElement
                intoParameters:catalogueParsedParameters];

  [self parseColorskinFromElement:configElement
                   intoParameters:catalogueParsedParameters];

  [self parsePaymentDataFromElement:&element
                     intoParameters:catalogueParsedParameters];

  [self parseShoppingCartOptionsFromElement:configElement
                             intoParameters:catalogueParsedParameters];

  [params_ setObject:catalogueParsedParameters forKey:kCatalogueParsedParametersKey];

  BOOL dbIsReady = [self prepareDatabaseAtPath:[mCatalogueParameters dbFilePath:[params_ objectForKey:@"module_id"]]];

  if(dbIsReady){
    [self persistCatalogueContents:element];
  }
}

+(void)parseParamsFromElement:(TBXMLElement *)element
               intoParameters:(NSMutableDictionary *)parametersDict
{
  TBXMLElement *mCatalogueParamElement = element->firstChild;

  NSArray *tagList = [NSArray arrayWithObjects:
                      @"title",
                      @"module_id",
                      @"app_id",
                      @"app_name",
                      @"currency",
                      @"mainpagestyle",
                      @"enabled_buttons",
                      @"showimages",
                      nil];

  while( mCatalogueParamElement )
  {
    NSString *elementName = [[TBXML elementName:mCatalogueParamElement] lowercaseString];
    if ( [tagList containsObject:elementName] )
    {
      NSString *tagContent = [TBXML textForElement:mCatalogueParamElement];

      if ( [tagContent length] )

        [parametersDict setValue:tagContent forKey:elementName];
    }
    mCatalogueParamElement = mCatalogueParamElement->nextSibling;
  }
}

+(void)parseColorskinFromElement:(TBXMLElement *)element
                  intoParameters:(NSMutableDictionary *)parametersDict
{
  // search for tag <colorskin>
  TBXMLElement *colorskinElement = [TBXML childElementNamed:@"colorskin" parentElement:element];
  if (colorskinElement)
  {
    TBXMLElement *colorElement = colorskinElement->firstChild;
    while( colorElement )
    {
      NSString *colorElementContent = [TBXML textForElement:colorElement];

      if ( [colorElementContent length] )
        [parametersDict setValue:colorElementContent forKey:[[TBXML elementName:colorElement] lowercaseString]];

      colorElement = colorElement->nextSibling;
    }
  }
}

+(void)parsePaymentDataFromElement:(TBXMLElement *)element
                    intoParameters:(NSMutableDictionary *)parametersDict
{
  TBXMLElement *paymentDataElement = [TBXML childElementNamed:@"payment_data" parentElement:element];

  NSString *payPalClientId = nil;

  NSNumber *checkoutEnabled = @0;

  if(paymentDataElement){
    TBXMLElement *payPalElement = [TBXML childElementNamed:@"paypal" parentElement:paymentDataElement];

    if(payPalElement){
      TBXMLElement *clientId = [TBXML childElementNamed:@"client_id" parentElement:payPalElement];
      payPalClientId = [TBXML textForElement:clientId];

      if(payPalClientId.length){
        [parametersDict setValue:payPalClientId forKey:@"payPalClientId"];

        checkoutEnabled = @1;
      }
    }
  }

  [parametersDict setObject:checkoutEnabled forKey:@"checkoutEnabled"];
}

+(void)parseShoppingCartOptionsFromElement:(TBXMLElement *)element
                            intoParameters:(NSMutableDictionary *)parametersDict
{
  TBXMLElement *shoppingCartElement = [TBXML childElementNamed:@"shoppingcart" parentElement:element];

  NSNumber *cartEnabled = @0;

  if(shoppingCartElement){

    cartEnabled = @1;

    BOOL checkoutEnabled = [[parametersDict objectForKey:@"checkoutEnabled"] boolValue];

    if(!checkoutEnabled)
    {
      [self parseUserFillableFieldsFromElement:shoppingCartElement
                                intoParameters:parametersDict];
    }
  }

  [parametersDict setObject:cartEnabled forKey:@"cartEnabled"];
}

+(void)parseUserFillableFieldsFromElement:(TBXMLElement *)element
                           intoParameters:(NSMutableDictionary *)parametersDict
{
  mCatalogueUserProfile *userProfile = [mCatalogueUserProfile createWithXMLElement:[TBXML childElementNamed:@"orderform" parentElement:element]];
  mCatalogueConfirmInfo *confInfo = [mCatalogueConfirmInfo createWithXMLElement:[TBXML childElementNamed:@"orderconfirmation" parentElement:element]];
  NSString *cartDescription = @"";
  if ([TBXML childElementNamed:@"cartdescription" parentElement:element]) {
     cartDescription = [TBXML textForElement:[TBXML childElementNamed:@"cartdescription" parentElement:element]];
  }

  NSUserDefaults *preferences = [NSUserDefaults standardUserDefaults];

  NSString *currentLevelKey = @"cartdescription";

  [preferences setObject:cartDescription forKey:currentLevelKey];

    //  Save to disk
  const BOOL didSave = [preferences synchronize];

  if (!didSave)
  {
      //  Couldn't save (I've never seen this happen in real world testing)
  }
//  UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"ROFL"
//                                                  message:cartDescription
//                                                 delegate:self
//                                        cancelButtonTitle:@"OK"
//                                        otherButtonTitles:nil];
//  [alert show];

  mCatalogueUserProfileItem *note = userProfile.note;

  //we need this to present note as multiline view
  //it is only possible if note is a part of mCatalogueConfirmInfo
  if(note){
    NSMutableArray *fields = [[userProfile.fields mutableCopy] autorelease];

    NSUInteger indexOfNote = [userProfile.fields indexOfObject:note];
    [fields removeObjectAtIndex:indexOfNote];
    [userProfile setFields:fields];

    confInfo.note = note;
  }

  NSData *profileData = [NSKeyedArchiver archivedDataWithRootObject:userProfile];
  NSData *confInfoData = [NSKeyedArchiver archivedDataWithRootObject:confInfo];

  [parametersDict setObject:profileData forKey:mCatalogueUserProfileKey];
  [parametersDict setObject:confInfoData forKey:mCatalogueOrderConfirmInfoKey];
}

/**
 *  Parsing tags and attributes for XML node
 *
 *  @param tagsList      array of valid tag names
 *  @param parentElement XML node
 *
 *  @return Mutable dictionary with parsed data
 */
+ (NSMutableDictionary*) getElementsDictionaryWithTags:(NSArray*)tagsList andParent:(TBXMLElement*)parentElement
{
  NSMutableDictionary *elementMap = [[[NSMutableDictionary alloc] init] autorelease];
  for( NSString *tag in tagsList )
    {
    TBXMLElement *subElement = [TBXML childElementNamed:tag parentElement:parentElement];
    if ( subElement )
      [elementMap setObject:[TBXML textForElement:subElement] forKey:[TBXML elementName:subElement]];
    }

    // processing attributes for <item>:
  TBXMLAttribute * attribute = parentElement->firstAttribute;

    // if attribute is valid
  while (attribute)
    {
    [elementMap setObject:[TBXML attributeValue:attribute] forKey:[TBXML attributeName:attribute]];
      // Obtain the next attribute
    attribute = attribute->next;
    }

  return elementMap;
}

#pragma mark - DB
/**
 * Prepare database: create file and schema if needed
 * @return BOOL succeeded - whether db is ready for use
 */
+ (BOOL)prepareDatabaseAtPath:(NSString *)dbPath{
    //Due to our DB Manager is static variable, but there could be several mCatalogue modules
    //with different db, but one module at a time.
    //So let's release and rewrite DB Manager every time new mCatalogue module launches.
  if(catalogueDBManager){
    [catalogueDBManager release];
    catalogueDBManager = nil;
  }

  catalogueDBManager = [[mCatalogueDBManager alloc] initWithDatabaseNamed:dbPath];

  NSError *error = [catalogueDBManager openDatabase];

  if ( error ){
      // can't open database, so database doesn't exists, create database file
    BOOL result = [[NSFileManager defaultManager] createFileAtPath:dbPath
                                                          contents:nil
                                                        attributes:nil];
    if ( !result ){
      [catalogueDBManager release];
      catalogueDBManager = nil;
      return NO;
    }

      // now, try to open database
    error = [catalogueDBManager openDatabase];
    if ( error ){
      [catalogueDBManager release];
      catalogueDBManager = nil;
      return NO;
    }

  }

    // create tables in database
  [catalogueDBManager createTables];
  [catalogueDBManager closeDatabase];

  return YES;
}

+(void)persistCatalogueContents:(TBXMLElement)element
{
  BOOL categoriesPersisted = YES;
  BOOL itemsPersisted = YES;

  [catalogueDBManager openDatabase];
  [catalogueDBManager beginTransaction];

  /*
   * Better way: since we have config with categories and products with "valid" = 1 or 0
   * If valid = 0, we delete that entries from DB. If 1, we just update.
   */
  [catalogueDBManager deleteCategories];
  [catalogueDBManager deleteProducts];

  // search for tag <category>
  categoriesPersisted = [mCatalogueViewController persistCategoriesWithDBManager:catalogueDBManager parentElement:element];
  // search for tag <item>
  itemsPersisted = [mCatalogueViewController persistItemsWithDBManager:catalogueDBManager parentElement:element];

  [catalogueDBManager commitTransaction];
  [catalogueDBManager closeDatabase];

  NSLog(@"mCatalogue categories persisted: %@\nitems persisted %@",
        categoriesPersisted ? @"OK" : @"FAIL",
             itemsPersisted ? @"OK" : @"FAIL");
}

+(BOOL)persistCategoriesWithDBManager:(const mCatalogueDBManager *)dbManager
                        parentElement:(TBXMLElement)element
{
  BOOL persistenceSucceeded = YES;

  NSArray *subTagList = @[@"categoryname",
                          @"categoryimg",
                          @"categoryimg_res"];

  TBXMLElement *categoryElement = [TBXML childElementNamed:@"categories" parentElement:&element]->firstChild;

  NSMutableArray *categories = [[NSMutableArray alloc] init];

  while (categoryElement)
    {
    NSMutableDictionary *categoryElementMap = [[NSMutableDictionary alloc] init];

    // processing attributes for <category>:
    TBXMLAttribute * attribute = categoryElement->firstAttribute;

    while (attribute)
      {
      [categoryElementMap setObject:[TBXML attributeValue:attribute] forKey:[TBXML attributeName:attribute]];
      attribute = attribute->next;
      }

    // processing sub tags for <category>
    for( NSString *tag in subTagList )
      {
      TBXMLElement *subElement = [TBXML childElementNamed:tag parentElement:categoryElement];
      if (!subElement)
        continue;

      [categoryElementMap setObject:[TBXML textForElement:subElement] forKey:[TBXML elementName:subElement]];
      }

    mCatalogueCategory *category = [[mCatalogueCategory alloc] initWithDictionary:categoryElementMap];
    [categories addObject:category];
    [category release];

    [categoryElementMap release];

    categoryElement = [TBXML nextSiblingNamed:[TBXML elementName:categoryElement] searchFromElement:categoryElement];

    if([categories count] == kCatalogueCategoryBatchCapacity){
      persistenceSucceeded &= [dbManager insertCategories:categories];
      [categories release];

      categories = [[NSMutableArray alloc] init];
    }
    }

  if([categories count]){
    persistenceSucceeded &= [dbManager insertCategories:categories];
    [categories release];
  } else if(categories){
    [categories release];
  }

  categories = nil;

  return persistenceSucceeded;
}

+(BOOL)persistItemsWithDBManager:(const mCatalogueDBManager *)dbManager
                   parentElement:(TBXMLElement)element
{
  BOOL persistenceSucceeded = YES;

  // sub tags in <item>
  NSArray *itemTagList = @[@"itemname",
                           @"itemdescription",
                           @"itemprice",
                           @"itemoldprice",
                           @"itemsku",
                           @"image",
                           @"image_res",
                           @"thumbnail",
                           @"thumbnail_res"];

  TBXMLElement *itemElement = [TBXML childElementNamed:@"items" parentElement:&element]->firstChild;

  NSMutableArray *items = [[NSMutableArray alloc] init];

  while (itemElement)
  {
    NSMutableDictionary *itemElementMap = [[NSMutableDictionary alloc] init];

    // processing attributes for <item>:
    TBXMLAttribute * attribute = itemElement->firstAttribute;

    while (attribute)
      {
      [itemElementMap setObject:[TBXML attributeValue:attribute] forKey:[TBXML attributeName:attribute]];
      attribute = attribute->next;
      }

    // processing sub tags for <category>
    for( NSString *tag in itemTagList )
      {
      TBXMLElement *subElement = [TBXML childElementNamed:tag parentElement:itemElement];
      if (!subElement)
        continue;

      [itemElementMap setObject:[TBXML textForElement:subElement] forKey:[TBXML elementName:subElement]];
      }

    mCatalogueItem *item = [[mCatalogueItem alloc] initWithDictionary:itemElementMap];
    [items addObject:item];
    [item release];

    [itemElementMap release];
    itemElement = itemElement->nextSibling;

    if([items count] == kCatalogueItemBatchCapacity){
      persistenceSucceeded &= [dbManager insertProducts:items];
      [items release];

      items = [[NSMutableArray alloc] init];
    }
  }

  if([items count]){
    persistenceSucceeded &= [dbManager insertProducts:items];
    [items release];
  } else if(items){
    [items release];
  }

  items = nil;

  return persistenceSucceeded;
}

-(void)retreiveEntriesByLike:(NSString *)token
{
  mCatalogueDBSearchResult searchResult = [catalogueDBManager searchForToken:token];

  [self processQueriedCategories:searchResult.categories andProducts:searchResult.products];
}

-(void)retreiveEntriesFromCategory:(NSInteger)categoryUid
{
  NSArray *queriedCategories = [catalogueDBManager selectCategoriesWithParentId:categoryUid];
  NSArray *queriedProducts = [catalogueDBManager selectProductsForCategoryId:categoryUid];

  [self processQueriedCategories:queriedCategories andProducts:queriedProducts];
}

-(void)processQueriedCategories:(NSArray *)queriedCategories
                    andProducts:(NSArray *)queriedProducts
{
  NSMutableArray *populatedCategories = [[NSMutableArray alloc] init];
    //uncomment if you want to show only categories with items (products) inside
  for (mCatalogueCategory *category in queriedCategories) {
      //if ([category.items count] || [category.subcategories count]){
    [populatedCategories addObject:category];
      //}
  }

  NSMutableArray *extractedCategories = [NSMutableArray array];
  NSMutableArray *extractedItems = [NSMutableArray array];

  BOOL topAndHavetSubCategory = NO;
  if (populatedCategories.count)
    {
    mCatalogueCategory *firstCategory = [populatedCategories objectAtIndex:0];
    topAndHavetSubCategory = firstCategory.parentCategoryUid == 0 && !firstCategory.subcategories.count;
    }

    // initially single top-level category was expanded
    // if there is only one category with items and no noncategorized items
    // show all the items/subcategories from the category on the top level
  if (topAndHavetSubCategory && ([populatedCategories count] == 1) && ![queriedProducts count]){

    mCatalogueCategory *category = [populatedCategories objectAtIndex:0];

    for(mCatalogueCategory *subcategoty in category.subcategories){
      [extractedCategories addObject:subcategoty];
    }

    for(mCatalogueItem *item in category.items){
      [extractedItems addObject:item];

      itemViewsShoulShowPlaceholder |= item.hasImage;
    }
  } else {
    [extractedCategories addObjectsFromArray:populatedCategories];

    for(mCatalogueItem *item in queriedProducts){
      [extractedItems addObject:item];

      itemViewsShoulShowPlaceholder |= item.hasImage;
    }
  }

  [self populateAssortmentWithCategories:extractedCategories andItems:extractedItems];
}

-(void)populateAssortmentWithCategories:(NSMutableArray *)categories
                               andItems:(NSMutableArray *)items
{
  NSMutableArray *categoriesToPopulate;
  NSMutableArray *itemsToPopulate;

  if(_catalogueParams.isGrid){
      //To preserve correct grid layout we do not allow the number of categories to be odd
      //so we add a fake "category" to have our products start from new row
    if(categories.count % 2){
      [categories addObject:[NSNull null]];
    }

    categoriesToPopulate = [NSMutableArray array];
    itemsToPopulate = [NSMutableArray array];

    [self populateCatalogueEntryPairsArray:categoriesToPopulate withEntriesFromSourceArray:categories];
    [self populateCatalogueEntryPairsArray:itemsToPopulate withEntriesFromSourceArray:items];

  } else {

    categoriesToPopulate = categories;
    itemsToPopulate = items;

  }

  [self.assortment setObject:categoriesToPopulate forKey:kCatalogueAssortmentCategoriesKey];
  [self.assortment setObject:itemsToPopulate forKey:kCatalogueAssortmentItemsKey];

  categoriesCount = [categoriesToPopulate count];
  itemsCount = [itemsToPopulate count];
}

- (void)populateCatalogueEntryPairsArray:(NSMutableArray *)entryPairsArray
              withEntriesFromSourceArray:(NSArray *)sourceArray
{
  if(!entryPairsArray || !sourceArray){
    return;
  }

  NSUInteger entriesCount = sourceArray.count;

  for(NSUInteger i = 0; i < entriesCount; i += 2){
    NSArray *pairArray;

    if(i + 1 != entriesCount){
      pairArray = @[sourceArray[i], sourceArray[i+1]];
    } else {
      pairArray = @[sourceArray[i]];
    }
    [entryPairsArray addObject:pairArray];
  }
}

-(void)retreiveData
{
  if([self isInSearchMode]){
    [self retreiveEntriesByLike:_searchToken];

    NSArray *categories = [self.assortment objectForKey:kCatalogueAssortmentCategoriesKey];
    NSArray *items = [self.assortment objectForKey:kCatalogueAssortmentItemsKey];

    if(!categories || ![categories count]){
      if(!items || ![items count]){
        [self placeNoResultsLabel];
      }
    }
  } else {
    [self retreiveEntriesFromCategory:_categoryToShow];
  }
}

#pragma mark - Input params processing
- (void)setParams:(NSMutableDictionary *)inputParams
{
  [self processInputParams:inputParams];

  NSDictionary *catalogueParsedParameters = [inputParams objectForKey:kCatalogueParsedParametersKey];
  [self processCatalogueParsedParams:catalogueParsedParameters];

  self.title = [inputParams objectForKey:@"title"];
  [self.navigationItem setTitle:_catalogueParams.pageTitle];
}

-(void)processInputParams:(NSDictionary *)inputParams
{
  _catalogueParams.pageTitle = [inputParams objectForKey:@"title"];
  _catalogueParams.showLink = [[inputParams objectForKey:@"showLink"] boolValue];

  if ([inputParams objectForKey:@"app_id"])
    _catalogueParams.appID = [inputParams objectForKey:@"app_id"];
  else
    _catalogueParams.appID  = @"";

  if ([inputParams objectForKey:@"appName"])
    _catalogueParams.appName = [inputParams objectForKey:@"appName"];
  else
    _catalogueParams.appName  = @"";

  if ([inputParams objectForKey:@"module_id"])
    _catalogueParams.moduleID = [inputParams objectForKey:@"module_id"];
  else
    _catalogueParams.moduleID  = @"";

  NSString *widgetId = [inputParams objectForKey:@"widget_id"];
  _catalogueParams.widgetId = [widgetId integerValue];
}

-(void)processCatalogueParsedParams:(NSDictionary *)catalogueParsedParameters
{
  if (!catalogueParsedParameters || [catalogueParsedParameters count] == 0){
    NSLog(@"parametersDict is empty!!!");
  }

  _catalogueParams.currencyCode = [catalogueParsedParameters objectForKey:@"currency"];

  _catalogueParams.showImages = [[catalogueParsedParameters objectForKey:@"showimages"] isEqualToString:@"on"];
  _catalogueParams.isGrid = [[catalogueParsedParameters objectForKey:@"mainpagestyle"] isEqualToString:@"grid"];
  _catalogueParams.enabledButtons = [catalogueParsedParameters objectForKey:@"enabled_buttons"];
  NSString *s = [catalogueParsedParameters objectForKey:@"enabled_buttons"];

  [[NSUserDefaults standardUserDefaults] setObject:s forKey:@"enabled_buttons"];
  [[NSUserDefaults standardUserDefaults] synchronize];

  NSString *color1String = [catalogueParsedParameters objectForKey:@"color1"];

  if (color1String)
    _catalogueParams.backgroundColor  = [color1String asColor];
  else
    _catalogueParams.backgroundColor  = [UIColor lightGrayColor];

  if([color1String isEqualToString:@"#ffffff"] || [color1String isEqualToString:@"#fff"] || /*Quite impossible, but give it a chance*/ [color1String isEqualToString:@"white"]) {
    _catalogueParams.isWhiteBackground = YES;
  }
  else {
    _catalogueParams.isWhiteBackground = NO;
  }

  if ([catalogueParsedParameters objectForKey:@"color2"])
    _catalogueParams.categoryTitleColor  = [[catalogueParsedParameters objectForKey:@"color2"] asColor];
  else
    _catalogueParams.categoryTitleColor     = [UIColor yellowColor];

  if ([catalogueParsedParameters objectForKey:@"color3"])
    _catalogueParams.captionColor  = [[catalogueParsedParameters objectForKey:@"color3"] asColor];
  else
    _catalogueParams.captionColor = [UIColor yellowColor];

  if ([catalogueParsedParameters objectForKey:@"color4"])
    _catalogueParams.descriptionColor  = [[catalogueParsedParameters objectForKey:@"color4"] asColor];
  else
    _catalogueParams.descriptionColor = [UIColor whiteColor];

  if ([catalogueParsedParameters objectForKey:@"color5"])
    _catalogueParams.priceColor  = [[catalogueParsedParameters objectForKey:@"color5"] asColor];
  else
    _catalogueParams.priceColor = [UIColor blackColor];

  /**
   * At this point catalogueDBManager holds a value of last-used manager
   * Now we obtain and store to that variable a manager, sepcific to our module
   */
  [mCatalogueViewController prepareDatabaseAtPath:[mCatalogueParameters dbFilePath:_catalogueParams.moduleID]];

  _catalogueParams.dbManager = catalogueDBManager;

  NSString *payPalClientId = [catalogueParsedParameters objectForKey:@"payPalClientId"];

  if(payPalClientId.length){
    [IBPPayPalManager initializePayPalWithClientId:payPalClientId];
  }

  _catalogueParams.payPalClientId = payPalClientId;

  _catalogueParams.cartEnabled = [[catalogueParsedParameters objectForKey:@"cartEnabled"] integerValue]; //BOOL

  NSUserDefaults *preferences = [NSUserDefaults standardUserDefaults];

  NSString *cartEnabledKey = @"cartEnabled";

  const BOOL cartEnabled = _catalogueParams.cartEnabled;
  [preferences setBool:cartEnabled forKey:cartEnabledKey];

    //  Save to disk
  [preferences synchronize];

  _catalogueParams.checkoutEnabled = [[catalogueParsedParameters objectForKey:@"checkoutEnabled"] integerValue]; //BOOL

  if(_catalogueParams.cartEnabled && !_catalogueParams.checkoutEnabled){
    _catalogueParams.confirmInfo = [NSKeyedUnarchiver unarchiveObjectWithData:[catalogueParsedParameters objectForKey:mCatalogueOrderConfirmInfoKey]];
    _catalogueParams.userProfile = [NSKeyedUnarchiver unarchiveObjectWithData:[catalogueParsedParameters objectForKey:mCatalogueUserProfileKey]];

    [self fillUserProfileWithSerializedParamsIfAvailable];
  }

  _catalogueParams.cart = [catalogueDBManager selectCartContents];
}

-(void)fillUserProfileWithSerializedParamsIfAvailable
{
  mCatalogueParameters *serializedParameters = [mCatalogueParameters deserializeParametersWithModuleID:_catalogueParams.moduleID];

  if(serializedParameters){
    _catalogueParams.userProfile = serializedParameters.userProfile;
  }
}

#pragma mark - Interface
-(void)placeTableView
{
  CGRect catalogueTableViewFrame = CGRectOffset(self.view.bounds, 0.0f, CGRectGetMaxY(self.customNavBar.frame));
  catalogueTableViewFrame.size.height -= catalogueTableViewFrame.origin.y;

  self.catalogueTableView = [[UITableView alloc] initWithFrame:catalogueTableViewFrame style:UITableViewStylePlain];
  _catalogueTableView.autoresizesSubviews = YES;
  _catalogueTableView.autoresizingMask    = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
  _catalogueTableView.delegate            = self;
  _catalogueTableView.dataSource          = self;

  [_catalogueTableView setShowsHorizontalScrollIndicator:NO];
  [_catalogueTableView setShowsVerticalScrollIndicator  :NO];

  _catalogueTableView.backgroundColor = self.view.backgroundColor;

  _catalogueTableView.backgroundColor = _catalogueTableView.backgroundColor;

  _catalogueTableView.separatorColor = [UIColor clearColor];

  [self.view insertSubview:self.catalogueTableView belowSubview:self.customNavBar];
}

- (void)placeNoResultsLabel
{
  CGFloat maxLabelWidth = self.view.bounds.size.width - 2*kCatalogueNoResultsFoundLabelLeftMargin;

  UILabel *noResultsLabel = [[UILabel alloc] init];
  noResultsLabel.numberOfLines = 0;
  noResultsLabel.textColor = _catalogueParams.captionColor;
  noResultsLabel.textAlignment = NSTextAlignmentCenter;
  noResultsLabel.text = NSBundleLocalizedString(@"mCatalogue_NoResultsFound", @"There is no result for your query");
  noResultsLabel.backgroundColor = self.view.backgroundColor;
  noResultsLabel.lineBreakMode = NSLineBreakByWordWrapping;

  CGSize actualLabelSize = [noResultsLabel.text sizeForFont:noResultsLabel.font
                                                  limitSize:(CGSize){maxLabelWidth, CGFLOAT_MAX}
                                              lineBreakMode:noResultsLabel.lineBreakMode];

  CGRect noResultsLabelFrame = (CGRect){
    kCatalogueNoResultsFoundLabelLeftMargin,
    kCatalogueNoResultsFoundLabelOriginY + CGRectGetMaxY(self.customNavBar.frame),
    maxLabelWidth,
    actualLabelSize.height
  };

  noResultsLabel.frame = noResultsLabelFrame;

  [self.view addSubview:noResultsLabel];

  [noResultsLabel release];
}

-(void)addTapRecognizerToEntryView:(mCatalogueEntryView *)view{

  if(view){
    UITapGestureRecognizer *recognizer;

    if([view isKindOfClass:[mCatalogueItemView class]]){
      recognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(showItem:)];
    } else if([view isKindOfClass:[mCatalogueCategoryView class]]){
      recognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(showCategoryContent:)];
    } else {
      return;
    }

    [view addGestureRecognizer:recognizer];
    [recognizer release];
  }
}

-(void)customizeNavBarAppearanceCompleted:(NSNotification *)notification
{
  if(isFirstPage){
    initialStatusBarStyle = [[UIApplication sharedApplication] statusBarStyle];
  }

  [super customizeNavBarAppearanceCompleted:notification];
}

#pragma mark - View lifecycle

- (void)viewDidLoad
{
  [super viewDidLoad];

  isFirstPage = ([self.navigationController.viewControllers indexOfObject:self] == kCatalogueInitialControllerIndexInStack);

  if(isFirstPage){
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(likedItemsLoaded:)
                                                 name:k_auth_Share_LikedItemsLoadedNotificationName
                                               object:nil];

    self.customNavBar.backButtonLabel.text = NSLocalizedString(@"core_rootViewControllerTitle", @"Home");
  }

  self.customNavBar.cartButtonHidden = ![mCatalogueParameters sharedParameters].cartEnabled;

  self.customNavBar.cartButton.sideBarModuleAction.target = self;
  self.customNavBar.cartButton.sideBarModuleAction.selector = @selector(gotoCart);

  self.view.backgroundColor = _catalogueParams.backgroundColor;

  [self placeTableView];

  [self retreiveData];

  [self loadLikedItemsIfNeeded];
}

-(void)viewWillAppear:(BOOL)animated
{
  // before hiding / displaying tabBar we must remember its previous state
  [super viewWillAppear:NO];

  self.customNavBar.title = self.title;

  UIEdgeInsets contentInset =  self.catalogueTableView.contentInset;
  CGRect actualizedCatalogueTableView = _catalogueTableView.frame;

  if (_catalogueParams.isGrid) {
    contentInset.top = kCatalogueTableRowGap_Grid;
  }
  else {
    contentInset.top = 0.0f;
    contentInset.bottom = kCatalogueTableRowGap_Grid;
  }

  _catalogueTableView.frame = actualizedCatalogueTableView;
  _catalogueTableView.contentInset = contentInset;

  [self loadLikedItemsIfNeeded];
}

#pragma mark - UITableViewDatasource
- (UITableViewCell*)tableView:(UITableView *)tableView
        cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
  static NSString *cellIdentifier = @"CatalogueEntryCell";

  UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];

  NSArray *categories = [self.assortment objectForKey:kCatalogueAssortmentCategoriesKey];
  NSArray *items = [self.assortment objectForKey:kCatalogueAssortmentItemsKey];

  if(_catalogueParams.isGrid){
    mCatalogueEntryView *firstView = nil;
    mCatalogueEntryView *secondView = nil;

    if(!cell){
      cell = [[[mCatalogueGridCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier] autorelease];
      cell.userInteractionEnabled = YES;
      cell.selectionStyle = UITableViewCellSelectionStyleNone;
      cell.backgroundColor = self.catalogueTableView.backgroundColor;
    }

    NSArray *catalogueEntryPair = nil;

    if(indexPath.row < categoriesCount){
      //it's grid, we show pair of categories
      catalogueEntryPair = categories[indexPath.row];

      firstView = [[[mCatalogueCategoryView alloc] initWithCatalogueEntryViewStyle:mCatalogueEntryViewStyleGrid] autorelease];

      mCatalogueCategory *firstCategory = [catalogueEntryPair firstObject];
      ((mCatalogueCategoryView *)firstView).catalogueCategory = firstCategory;
      firstView.backgroundColor = _catalogueParams.backgroundColor;

      if(_catalogueParams.isWhiteBackground){
        ((mCatalogueCategoryView *)firstView).imagePlaceholderMaskColor = kCatalogueCategoryDarkMaskColor;
      }

      mCatalogueCategory *secondCategory = [categories[indexPath.row] lastObject];

      if((id)secondCategory != (id)[NSNull null]){
        secondView = [[[mCatalogueCategoryView alloc] initWithCatalogueEntryViewStyle:mCatalogueEntryViewStyleGrid] autorelease];

        ((mCatalogueCategoryView *)secondView).catalogueCategory = secondCategory;
        secondView.backgroundColor = _catalogueParams.backgroundColor;

        if(_catalogueParams.isWhiteBackground){
          ((mCatalogueCategoryView *)secondView).imagePlaceholderMaskColor = kCatalogueCategoryDarkMaskColor;
        }
      }
    }
    else {
      //it's grid, we show pair of items
      NSUInteger itemIndex = indexPath.row - categoriesCount;

      mCatalogueItemView *firstItemView = [[[mCatalogueItemView alloc] initWithCatalogueEntryViewStyle:mCatalogueEntryViewStyleGrid] autorelease];
      firstView = firstItemView;

      catalogueEntryPair = items[itemIndex];

      mCatalogueItem *firstItem = [catalogueEntryPair firstObject];
      firstItemView.catalogueItem = firstItem;
      [firstItemView showPlaceholder:itemViewsShoulShowPlaceholder];
      firstItemView.delegate = self;
      firstView.backgroundColor = kCatalogueItemBackgroundColor;

      if(catalogueEntryPair.count == 2){
        mCatalogueItem *secondItem = [catalogueEntryPair lastObject];

        if(secondItem != (id)[NSNull null]){
          mCatalogueItemView *secondItemView = [[[mCatalogueItemView alloc] initWithCatalogueEntryViewStyle:mCatalogueEntryViewStyleGrid] autorelease];
          secondView = secondItemView;

          secondItemView.catalogueItem = secondItem;
          [secondItemView showPlaceholder:itemViewsShoulShowPlaceholder];
          secondItemView.delegate = self;
          secondView.backgroundColor = kCatalogueItemBackgroundColor;
        }
      }
    }

    [self addTapRecognizerToEntryView:firstView];
    [self addTapRecognizerToEntryView:secondView];

    firstView.catalogueParameters = _catalogueParams;
    secondView.catalogueParameters = _catalogueParams;

    ((mCatalogueGridCell *)cell).firstView = firstView;
    ((mCatalogueGridCell *)cell).secondView = secondView;

  } else {
    mCatalogueEntryView *catalogueEntryView = nil;

    if(!cell){
      cell = [[[mCatalogueRowCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier] autorelease];
      cell.userInteractionEnabled = YES;
      cell.selectionStyle = UITableViewCellSelectionStyleNone;
      cell.backgroundColor = self.catalogueTableView.backgroundColor;
    }

    if(indexPath.row < categoriesCount){
      //it's rows, show screen-wide category
      catalogueEntryView = [[[mCatalogueCategoryView alloc] initWithCatalogueEntryViewStyle:mCatalogueEntryViewStyleRow] autorelease];

      mCatalogueCategory *category = [categories objectAtIndex:indexPath.row];
      ((mCatalogueCategoryView *)catalogueEntryView).catalogueCategory = category;
      ((mCatalogueCategoryView *)catalogueEntryView).catalogueParameters = _catalogueParams;

      catalogueEntryView.backgroundColor = _catalogueParams.backgroundColor;

      if(_catalogueParams.isWhiteBackground){
        ((mCatalogueCategoryView *)catalogueEntryView).imagePlaceholderMaskColor = kCatalogueCategoryDarkMaskColor;
      } else {
        ((mCatalogueCategoryView *)catalogueEntryView).imagePlaceholderMaskColor = catalogueEntryView.backgroundColor;
      }
    }
    else {
     //it's rows, show screen-wide item
      NSUInteger itemIndex = indexPath.row - categoriesCount;

      mCatalogueItemView *itemView = [[[mCatalogueItemView alloc] initWithCatalogueEntryViewStyle:mCatalogueEntryViewStyleRow] autorelease];
      catalogueEntryView = itemView;

      mCatalogueItem *item = [items objectAtIndex:itemIndex];
      itemView.catalogueItem = item;
      [itemView showPlaceholder:itemViewsShoulShowPlaceholder];
      itemView.delegate = self;

      catalogueEntryView.backgroundColor = kCatalogueItemBackgroundColor;
    }

    [self addTapRecognizerToEntryView:catalogueEntryView];

    catalogueEntryView.catalogueParameters = _catalogueParams;
    ((mCatalogueRowCell *) cell).catalogueEntryView = catalogueEntryView;
  }

  return cell;
}

-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
  return categoriesCount + itemsCount;
}

#pragma mark - UITableViewDelegate
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
  mCatalogueEntryViewStyle style = _catalogueParams.isGrid ? mCatalogueEntryViewStyleGrid : mCatalogueEntryViewStyleRow;

  CGFloat rowGap = style == mCatalogueEntryViewStyleGrid ? kCatalogueTableRowGap_Grid : kCatalogueTableRowGap_Row;

  CGFloat height = 0.0f;

  //Categories always come first
  if(indexPath.row < categoriesCount){
    height = [mCatalogueCategoryView sizeForStyle:style withPlaceholder:NO].height;

    if(style == mCatalogueEntryViewStyleGrid){
      height += rowGap;
    } else {
      //do not add category gap to the last category,
      //because product gap is added
      //if(indexPath.row < categoriesCount - 1){
        height += kCatalogCategoryRowGap_Row;
      //}
    }
  }
  else {
    height = [mCatalogueItemView sizeForStyle:style
                              withPlaceholder:itemViewsShoulShowPlaceholder].height + rowGap;
  }
  return height;
}

#pragma mark - mCatalogue Entry tap recognizer actions

-(void)showItem:(UITapGestureRecognizer *)recognizer
{
  mCatalogueItem *item = ((mCatalogueItemView *) recognizer.view) .catalogueItem;

  mCatalogueItemVC *itemVC = [[mCatalogueItemVC alloc] initWithCatalogueItem:item];

  itemVC.title = isFirstPage ? _catalogueParams.pageTitle : self.title;

  [self.navigationController pushViewController:itemVC animated:YES];

  [itemVC release];

}

-(void)showCategoryContent:(UITapGestureRecognizer *)recognizer
{
  mCatalogueCategory *category = ((mCatalogueCategoryView *) recognizer.view) .catalogueCategory;

  mCatalogueViewController *categoryVC = [[mCatalogueViewController alloc] initWithNibName:nil bundle:nil];

  categoryVC.categoryToShow = category.uid;
  categoryVC.title = category.name;

  categoryVC.showTabBar = NO;
  categoryVC.tabBarIsHidden = YES;

  [self.navigationController pushViewController:categoryVC animated:YES];
  [categoryVC release];
}

#pragma mark - mCatalogue DB Operation delegates

-(void)didFinishUpdateOperationWithResult:(NSDictionary *)result{
  NSLog(@"didFinishUpdateOperation");
}

-(void)didFinishSelectOperationWithResult:(NSDictionary *)result {
  NSLog(@"didFinishSelectOperation");
}

#pragma mark - mCatalogue SearchView delegate

-(void)mCatalogueSearchViewDidShowSearchField{
  NSLog(@"mCatalogue show search bar");

  cancelSearchGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(cancelSearch:)];

  UIView *maskView = [[UIView alloc] initWithFrame:self.catalogueTableView.frame];
  maskView.backgroundColor = [UIColor clearColor];
  maskView.tag = kCatalogueMaskViewTag;
  [maskView addGestureRecognizer:cancelSearchGestureRecognizer];
  [self.view insertSubview:maskView belowSubview:self.customNavBar];
  [maskView release];

  [cancelSearchGestureRecognizer release];
}

/**
 * Method for handling taps on "<Back"
 */
-(void)mCatalogueSearchViewLeftButtonPressed{
  if(self.isInSearchMode){
    [self.navigationController popToViewController:self.navigationController.viewControllers[kCatalogueInitialControllerIndexInStack] animated:YES];
  } else {
    if(isFirstPage){
      [[NSNotificationCenter defaultCenter] removeObserver:self
                                                      name:k_auth_Share_LikedItemsLoadedNotificationName
                                                    object:nil];

      [[UIApplication sharedApplication] setStatusBarStyle:initialStatusBarStyle];

      [aSha cancelPendingTasksIfAny];

      [self clearImages];
    }

    [self.navigationController popViewControllerAnimated:YES];
  }
}

-(void)mCatalogueSearchViewSearchInitiated:(NSString *)searchToken{
  NSLog(@"mCatalogue Search");

  if(searchToken && [searchToken length]){
    mCatalogueViewController *categoryVC = [[mCatalogueViewController alloc] initWithNibName:nil bundle:nil];

    categoryVC.inSearchMode = YES;
    categoryVC.searchToken = searchToken;
    categoryVC.categoryToShow = 0;
    categoryVC.title = NSBundleLocalizedString(@"mCatalogue_SearchTitle", @"Search results");

    categoryVC.showTabBar = NO;
    categoryVC.tabBarIsHidden = YES;

    [self.navigationController pushViewController:categoryVC animated:YES];
    [categoryVC release];

    [self.customNavBar cancelSearch];
  }
}

-(void)mCatalogueSearchViewDidCancelSearch{
  //assume that recognzer set on maskView
  UIView *maskView = [self.view viewWithTag:kCatalogueMaskViewTag];

  if(cancelSearchGestureRecognizer){
    [maskView removeGestureRecognizer:cancelSearchGestureRecognizer];
    [maskView removeFromSuperview];
    cancelSearchGestureRecognizer = nil;
  }
}

-(void)cancelSearch:(UITapGestureRecognizer *) recognizer
{
  [self.customNavBar cancelSearch];
}

-(void)clearImages
{
  SDImageCache *imageCache = [SDImageCache sharedImageCache];
  [imageCache clearMemory];
  [imageCache cleanDisk];
}

-(void)loadLikedItemsIfNeeded
{
  if([_catalogueParams isInternetReachable]){
    /**
     * Let's request liked items now and use them when displaying item VC
     */
    if(aSha.user.authentificatedWith == auth_ShareServiceTypeFacebook){

      if(_catalogueParams.likedItemsLoadingState == mCatalogueLikedFacebookItemsLoadingNotStarted ||
         _catalogueParams.likedItemsLoadingState == mCatalogueLikedFacebookItemsLoadingFailed){

        [aSha loadFacebookLikedURLs];
        _catalogueParams.likedItemsLoadingState = mCatalogueLikedFacebookItemsLoadingInProgress;
      }
    }
  }
}

#pragma mark - auth_Share liked fb items loading handler
-(void)likedItemsLoaded:(NSNotification *)notification
{
  NSArray *likedItems = [notification.object allObjects];

  if(_catalogueParams.likedItemsLoadingState == mCatalogueLikedFacebookItemsLoadingInProgress){

    if(_catalogueParams.likedItems){
        //rare case - we have liked smth, but array of liked items was loading at that moment
        //so we put our like in temporary array. Let's merge the arrays
      [_catalogueParams.likedItems addObjectsFromArray:likedItems];
    } else {
      _catalogueParams.likedItems = [[likedItems mutableCopy] autorelease];
    }

    _catalogueParams.likedItemsLoadingState = mCatalogueLikedFacebookItemsLoadingCompletedSuccessfully;
  }
}

#pragma mark -
-(void)didReceiveMemoryWarning
{
  [self clearImages];
  [super didReceiveMemoryWarning];
}

@end


text:
module.exports = function(app) {
  require('./user_controller')(app);
};

redpajama_set_name: RedPajamaGithub


text:
( function ( mad, document ) {
	var document_head = document.head || document.getElementsByTagName( 'head' )[ 0 ];

	function create_style( css ) {
		if( !css ) {
			return null;
		}

		var style = document.createElement( 'style' );
		var style_sheet = style.styleSheet;

		style.setAttribute( 'type', 'text/css' );

		// IE
		if( style_sheet ) {
			style_sheet.cssText = css;
		} else {
			// THE WORLD
			style.insertBefore( document.createTextNode( css ), null );
		}

		document_head.insertBefore( style, null );

		return style;
	}

	function register_tags( tag ) {
		// flat arugments
		// identify object type
		// register tags found as string or tagName
		document.registerElement( tag );
	}

	mad.html = {
		create_style: create_style,
		register_tags: register_tags
	};

})( window.mad, document );


text:
$(document).ready(function() {
  window.app = $.extend(true, {
    authorize: function(login, password, cb) {

      var url = 'https://oauth.vk.com/authorize?client_id=4115910&scope=audio&redirect_uri=https://oauth.vk.com/blank.html&display=page&v=5.5&response_type=token&revoke=1';

      var authWind = Ti.UI.createWindow({ id: 'vkAuth', url: url, visible: true });
      var authToken;
      var stage = 0;

      authWind.addEventListener('page.load', function(e) {
        try {
          var url = e.url;
          var res = url.match(/access_token=(\w+)/);
          if( res && res[1] ) {
            authToken = res[1];
            authWind.close();
            cb(null, authToken);
          } else {
            var doc = authWind.getDOMWindow().document;
            if( stage == 0 ) {
              doc.forms.login_submit.email.value = login;
              doc.forms.login_submit.pass.value = password;
              doc.forms.login_submit.submit.click();
              stage++;
            } else {
              doc.getElementById('install_allow').click();
            }
          }
        } catch(e) {
          cb(e);
        }
      });
      authWind.open();
    }
  }, window.app);
});


text:
This is a re-upload of a collaboration project done for [CodeLinc v3 (2016)] (http://lincolnfinancialgroup.cvent.com/events/codelinc-2016/event-summary-f0d35edebafd49b88597a294c977162c.aspx). I collaborated on the project w/ [Jordan Luke Stack](https://github.com/jlstack), we were challenged to create an application that would incentivize volunteers for the [Junior Achievement](https://triadja.org/) foundation, a non-profit company that brings financial education to young children. I commited from a computer that was improperly configured for my GitHub account. I worked on the server-side Django framework, and my partner designed the front end side with the Bootstrap library.

[Link to original repository](https://github.com/jlstack/codelinc_ja)

![Opening page of the web project.](http://i.imgur.com/Swe31Vu.png)
*Opening picture of homepage layout. Left: link to Junior Achievement website volunteer form. Right: Assortment of most recently uploaded images in a collage format, leading to the image gallery.*

Inspiration

Hearing the need for increase in volunteerism, our immediate response was information. If potential volunteers were informed about just what the experience was like, we believe they would be more likely to get involved. Having a network specialized in sharing pictures of volunteering, allows those who might be hesitant to see exactly what to expect and what they're missing out on.

![Twitter and Instragram integration](http://i.imgur.com/zRhuK4v.png)
*Left: Instragram integration, pulls most recent images from authorized Instgram account, awaiting Instragram credentials of Junior Achievement company. Right: Twitter integration, pulling most recent tweets under #triadja, easily expandable to more hashtags.*

What it does

Functions as a social network for demonstrating the experience of volunteering. Bringing a reality to those who have little experience but want more. The badge system and work log format should even promote current volunteers to continue volunteering for increased incentives: verified proof of constant dedication to a great cause.

![User Profile image](http://i.imgur.com/GZaq6VA.png)
*Image of user profile page. Features information about the hours logged of users, after verification from JA Administration. Displays badges earned and a cumulative number of hours volunteered.*

How we built it

We used Django framework, with Bootstrap and JQuery libraries. Django is a Python driven framework, with years of support and proven development releases.

![User Photo Page](http://i.imgur.com/zpKqW0t.png)
*Photos uploaded by the user, displayed in a collage format, as well as the footer organization.*

Challenges we ran into

We had great difficulty dealing with APIs that required real domains and server backend to use. We really wanted specific, important features, but unfortunately we ran into technical difficulties that were beyond our control. Given slightly more resources and a bit more time, we have great aspirations that would help this application grow.

![Snapshot of Django Administration](http://i.imgur.com/JTMhPOr.png)
*Image of the Administration page of Social JA. Junior Achievement administration can come here to approve user logged hours.*

Accomplishments that we're proud of

Our highest achievement had to be working as a team of two to accomplish tough challenges, meeting every challenge that was posed that was technically feasible. Certainly it was difficult, we didn't feel we could embrace the luxuries of break time. This was giving up valuable time to make our goal a reality. It was fortunate that we didn't; the time we dedicated continuously went towards making a rough goal possible.

![Specific Volunteer Hour Record](http://i.imgur.com/1dGtS7B.png)
*Image of specific volunteer hour record. All options can be edited and verification can be confirmed by admin.*

What we learned

We developed significantly greater experience with developing web applications, specifically in client-side design areas, including a responsive web design. Having little experience in front-end develop (and really in back-end also to be fair), we had to adapt and learn new skills on a tight deadline to meet our client's expectations.

What's next for Social JA

Our primary concern would be to implement our forum community. Engaging the volunteers or potential volunteers in conversation about past experiences or clarifying any uncertainties is a major goal for our project. It was really a critical blow to have to sacrifice such a critical feature (especially after meeting and discussing it with the director), but if we ever got the chance to continue our project, that would be our primary goal.


text:
module Fluent
  class Datagrids::PagesGrid
    include Datagrid

    scope do
      Page
    end

    filter(:title, :string) do |value|
      query = "%#{value}%"
      self.where('title LIKE :search', search: query)
    end
    filter(:slug, :string) do |value|
      query = "%#{value}%"
      self.where('slug LIKE :search', search: query)
    end

    column(:title, :header => I18n.t('activerecord.attributes.fluent/page.title'), :html => true) do |record|
      link_to record.title, edit_admin_page_path(record), :data => {:push => true}
    end
    column(:slug, :header => I18n.t('activerecord.attributes.fluent/page.slug'))
    column(:actions, :html => true, :header => I18n.t('backend_part.actions')) do |record|
      link_to(icon('pencil'), edit_admin_page_path(record), 'data-original-title' => t('backend_part.edit'), 'id' => 'tooltip', :data => {:push => true}) +
      link_to(icon('trash'), admin_page_path(record), 'data-original-title' => t('backend_part.remove'), 'id' => 'tooltip',  :method => :delete, :confirm => "#{t("backend_part.confirm")}")
    end

  end
end


text:
<title>Z8000 Opcodes - Using as</title>
<meta http-equiv="Content-Type" content="text/html">
<meta name="description" content="Using as">
<meta name="generator" content="makeinfo 4.11">
<link title="Top" rel="start" href="index.html#Top">
<link rel="up" href="Z8000_002dDependent.html#Z8000_002dDependent" title="Z8000-Dependent">
<link rel="prev" href="Z8000-Directives.html#Z8000-Directives" title="Z8000 Directives">
<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">

<meta http-equiv="Content-Style-Type" content="text/css">

Previous: Z8000 Directives,
Up: Z8000-Dependent

9.45.4 Opcodes

For detailed information on the Z8000 machine instruction set, see
Z8000 Technical Manual.


text:
// Copyright (c) 2012 Ecma International.  All rights reserved.
// Ecma International makes this code available under the terms and conditions set
// forth on http://hg.ecmascript.org/tests/test262/raw-file/tip/LICENSE (the
// "Use Terms").   Any redistribution of this code must retain the above
// copyright and this notice and otherwise comply with the Use Terms.

/*---
es5id: 15.4.4.21-9-3
description: >
    Array.prototype.reduce doesn't visit deleted elements in array
    after the call
includes: [runTestCase.js]
---*/

function testcase() {

  function callbackfn(prevVal, curVal, idx, obj)
  {
    delete arr[3];
    delete arr[4];
    return prevVal + curVal;
  }

  var arr = ['1',2,3,4,5];
  if(arr.reduce(callbackfn) === "123"  )    // two elements deleted
    return true;

 }
runTestCase(testcase);


text:
ACCEPTED

#### According to
Index Fungorum

#### Published in
null

#### Original name
Scolicotrichum dalbergiae Henn.

### Remarks
null


text:
using System.ComponentModel;

namespace LinqAn.Google.Dimensions
{
	/// <summary>
	/// 	A value that can be used to add flexibility in visualizing user timings in the reports.
	/// </summary>
	[Description("A value that can be used to add flexibility in visualizing user timings in the reports.")]
	public class UserTimingVariable: Dimension
	{
		/// <summary>
		/// 	Instantiates a <seealso cref="UserTimingVariable" />.
		/// </summary>
		public UserTimingVariable(): base("Timing Variable",true,"ga:userTimingVariable")
		{

		}
	}
}


text:
package io.spotnext.infrastructure.maven.xml;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlType;

/**
 *
Java class for RelationNode complex type.
 *
 *
The following schema fragment specifies the expected content contained within this class.
 *
 *

 * <complexType name="RelationNode">
 *   <complexContent>
 *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
 *       <sequence>
 *         <element name="description" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
 *         <element name="modifiers" type="{}Modifiers" minOccurs="0"/>
 *         <element name="annotations" type="{}Annotations" minOccurs="0"/>
 *       </sequence>
 *       <attribute name="itemType" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
 *       <attribute name="mappedBy" type="{http://www.w3.org/2001/XMLSchema}string" />
 *       <attribute name="cardinality" use="required" type="{}RelationshipCardinality" />
 *       <attribute name="collectionType" type="{}CollectionsType" default="Set" />
 *     </restriction>
 *   </complexContent>
 * </complexType>
 *

 *
 *
 */
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "RelationNode", propOrder = {
    "description",
    "modifiers",
    "annotations"
})
public class RelationNode {

    protected String description;
    protected Modifiers modifiers;
    protected Annotations annotations;
    @XmlAttribute(name = "itemType", required = true)
    protected String itemType;
    @XmlAttribute(name = "mappedBy")
    protected String mappedBy;
    @XmlAttribute(name = "cardinality", required = true)
    protected RelationshipCardinality cardinality;
    @XmlAttribute(name = "collectionType")
    protected CollectionsType collectionType;

    /**
     * Gets the value of the description property.
     *
     * @return
     *     possible object is
     *     {@link String }
     *
     */
    public String getDescription() {
        return description;
    }

    /**
     * Sets the value of the description property.
     *
     * @param value
     *     allowed object is
     *     {@link String }
     *
     */
    public void setDescription(String value) {
        this.description = value;
    }

    /**
     * Gets the value of the modifiers property.
     *
     * @return
     *     possible object is
     *     {@link Modifiers }
     *
     */
    public Modifiers getModifiers() {
        return modifiers;
    }

    /**
     * Sets the value of the modifiers property.
     *
     * @param value
     *     allowed object is
     *     {@link Modifiers }
     *
     */
    public void setModifiers(Modifiers value) {
        this.modifiers = value;
    }

    /**
     * Gets the value of the annotations property.
     *
     * @return
     *     possible object is
     *     {@link Annotations }
     *
     */
    public Annotations getAnnotations() {
        return annotations;
    }

    /**
     * Sets the value of the annotations property.
     *
     * @param value
     *     allowed object is
     *     {@link Annotations }
     *
     */
    public void setAnnotations(Annotations value) {
        this.annotations = value;
    }

    /**
     * Gets the value of the itemType property.
     *
     * @return
     *     possible object is
     *     {@link String }
     *
     */
    public String getItemType() {
        return itemType;
    }

    /**
     * Sets the value of the itemType property.
     *
     * @param value
     *     allowed object is
     *     {@link String }
     *
     */
    public void setItemType(String value) {
        this.itemType = value;
    }

    /**
     * Gets the value of the mappedBy property.
     *
     * @return
     *     possible object is
     *     {@link String }
     *
     */
    public String getMappedBy() {
        return mappedBy;
    }

    /**
     * Sets the value of the mappedBy property.
     *
     * @param value
     *     allowed object is
     *     {@link String }
     *
     */
    public void setMappedBy(String value) {
        this.mappedBy = value;
    }

    /**
     * Gets the value of the cardinality property.
     *
     * @return
     *     possible object is
     *     {@link RelationshipCardinality }
     *
     */
    public RelationshipCardinality getCardinality() {
        return cardinality;
    }

    /**
     * Sets the value of the cardinality property.
     *
     * @param value
     *     allowed object is
     *     {@link RelationshipCardinality }
     *
     */
    public void setCardinality(RelationshipCardinality value) {
        this.cardinality = value;
    }

    /**
     * Gets the value of the collectionType property.
     *
     * @return
     *     possible object is
     *     {@link CollectionsType }
     *
     */
    public CollectionsType getCollectionType() {
        if (collectionType == null) {
            return CollectionsType.SET;
        } else {
            return collectionType;
        }
    }

    /**
     * Sets the value of the collectionType property.
     *
     * @param value
     *     allowed object is
     *     {@link CollectionsType }
     *
     */
    public void setCollectionType(CollectionsType value) {
        this.collectionType = value;
    }

}


text:
package co.cask.cdap.common;

import co.cask.cdap.proto.Id;

/**
 * Thrown when a stream is not found
 */
public class StreamNotFoundException extends NotFoundException {

  private final Id.Stream id;

  public StreamNotFoundException(Id.Stream id) {
    super(id);
    this.id = id;
  }

  public Id.Stream getId() {
    return id;
  }
}


text:
require 'spec_helper'

describe 'time_picker input' do

  include FormtasticSpecHelper

  before do
    @output_buffer = ''
    mock_everything
  end

  context "with an object" do
    before do
      concat(semantic_form_for(@new_post) do |builder|
        concat(builder.input(:publish_at, :as => :time_picker))
      end)
    end

    it_should_have_input_wrapper_with_class(:time_picker)
    it_should_have_input_wrapper_with_class(:input)
    it_should_have_input_wrapper_with_class(:stringish)
    it_should_have_input_wrapper_with_id("post_publish_at_input")
    it_should_have_label_with_text(/Publish at/)
    it_should_have_label_for("post_publish_at")
    it_should_have_input_with_id("post_publish_at")
    it_should_have_input_with_type(:time)
    it_should_have_input_with_name("post[publish_at]")
    it_should_apply_custom_input_attributes_when_input_html_provided(:date_picker)
    it_should_apply_custom_for_to_label_when_input_html_id_provided(:date_picker)
    # TODO why does this blow-up it_should_apply_error_logic_for_input_type(:date_picker)

  end

  describe "size attribute" do

    it "defaults to 5 chars (HH:MM)" do
      concat(
        semantic_form_for(@new_post) do |f|
          concat(f.input(:publish_at, :as => :time_picker))
        end
      )
      output_buffer.should have_tag "input[size='5']"
    end

    it "can be set from :input_html options" do
      concat(
        semantic_form_for(@new_post) do |f|
          concat(f.input(:publish_at, :as => :time_picker, :input_html => { :size => "11" }))
        end
      )
      output_buffer.should have_tag "input[size='11']"
    end

    it "can be set from options (ignoring input_html)" do
      concat(
        semantic_form_for(@new_post) do |f|
          concat(f.input(:publish_at, :as => :time_picker, :size => '12', :input_html => { :size => "11" }))
        end
      )
      output_buffer.should have_tag "input[size='12']"
    end

  end

  describe "maxlength attribute" do

    it "defaults to 5 chars (HH:MM:SS)" do
      concat(
        semantic_form_for(@new_post) do |f|
          concat(f.input(:publish_at, :as => :time_picker))
        end
      )
      output_buffer.should have_tag "input[maxlength='5']"
    end

    it "can be set from :input_html options" do
      concat(
        semantic_form_for(@new_post) do |f|
          concat(f.input(:publish_at, :as => :time_picker, :input_html => { :maxlength => "11" }))
        end
      )
      output_buffer.should have_tag "input[maxlength='11']"
    end

    it "can be set from options (ignoring input_html)" do
      concat(
        semantic_form_for(@new_post) do |f|
          concat(f.input(:publish_at, :as => :time_picker, :maxlength => 12, :input_html => { :maxlength => "11" }))
        end
      )
      output_buffer.should have_tag "input[maxlength='12']"
    end

  end

  describe "value attribute" do

    context "when method returns nil" do

      it "has no value" do
        concat(
          semantic_form_for(@new_post) do |f|
            concat(f.input(:publish_at, :as => :time_picker ))
          end
        )
        output_buffer.should_not have_tag "li input[value]"
      end

      it "can be set from :input_html options" do
        concat(
          semantic_form_for(@new_post) do |f|
            concat(f.input(:publish_at, :as => :time_picker, :input_html => { :value => "12:00" }))
          end
        )
        output_buffer.should have_tag "input[value='12:00']"
      end

    end

    context "when method returns a Date" do

      before do
        @date = Date.new(2000, 11, 11)
        @new_post.stub!(:publish_at).and_return(@date)
      end

      it "renders 00:00" do
        concat(
          semantic_form_for(@new_post) do |f|
            concat(f.input(:publish_at, :as => :time_picker ))
          end
        )
        output_buffer.should have_tag "input[value='00:00']"
      end

      it "can be set from :input_html options" do
        concat(
          semantic_form_for(@new_post) do |f|
            concat(f.input(:publish_at, :as => :time_picker, :input_html => { :value => "23:59" }))
          end
        )
        output_buffer.should have_tag "input[value='23:59']"
      end

    end

    context "when method returns a Time" do

      before do
        @time = Time.utc(2000,11,11,11,11,11)
        @new_post.stub!(:publish_at).and_return(@time)
      end

      it "renders the time as a HH:MM" do
        concat(
          semantic_form_for(@new_post) do |f|
            concat(f.input(:publish_at, :as => :time_picker ))
          end
        )
        output_buffer.should have_tag "input[value='11:11']"
      end

      it "can be set from :input_html options" do
        concat(
          semantic_form_for(@new_post) do |f|
            concat(f.input(:publish_at, :as => :time_picker, :input_html => { :value => "12:12" }))
          end
        )
        output_buffer.should have_tag "input[value='12:12']"
      end

    end

    context "when method returns an empty String" do

      before do
        @new_post.stub!(:publish_at).and_return("")
      end

      it "will be empty" do
        concat(
          semantic_form_for(@new_post) do |f|
            concat(f.input(:publish_at, :as => :time_picker ))
          end
        )
        output_buffer.should have_tag "input[value='']"
      end

      it "can be set from :input_html options" do
        concat(
          semantic_form_for(@new_post) do |f|
            concat(f.input(:publish_at, :as => :time_picker, :input_html => { :value => "12:12:12" }))
          end
        )
        output_buffer.should have_tag "input[value='12:12:12']"
      end

    end

    context "when method returns a String" do

      before do
        @new_post.stub!(:publish_at).and_return("yeah")
      end

      it "will be the string" do
        concat(
          semantic_form_for(@new_post) do |f|
            concat(f.input(:publish_at, :as => :time_picker ))
          end
        )
        output_buffer.should have_tag "input[value='yeah']"
      end

      it "can be set from :input_html options" do
        concat(
          semantic_form_for(@new_post) do |f|
            concat(f.input(:publish_at, :as => :time_picker, :input_html => { :value => "12:12:12" }))
          end
        )
        output_buffer.should have_tag "input[value='12:12:12']"
      end

    end

  end

  describe "min attribute" do

    it "will be omitted by default" do
      concat(
        semantic_form_for(@new_post) do |f|
          concat(f.input(:publish_at, :as => :time_picker))
        end
      )
      output_buffer.should_not have_tag "input[min]"
    end

    it "can be set from :input_html options" do
      concat(
        semantic_form_for(@new_post) do |f|
          concat(f.input(:publish_at, :as => :time_picker, :input_html => { :min => "13:00" }))
        end
      )
      output_buffer.should have_tag "input[min='13:00']"
    end

  end

  describe "max attribute" do

    it "will be omitted by default" do
      concat(
        semantic_form_for(@new_post) do |f|
          concat(f.input(:publish_at, :as => :time_picker))
        end
      )
      output_buffer.should_not have_tag "input[max]"
    end

    it "can be set from :input_html options" do
      concat(
        semantic_form_for(@new_post) do |f|
          concat(f.input(:publish_at, :as => :time_picker, :input_html => { :max => "13:00" }))
        end
      )
      output_buffer.should have_tag "input[max='13:00']"
    end

  end

  describe "step attribute" do

    it "defaults to 60 (seconds)" do
      concat(
        semantic_form_for(@new_post) do |f|
          concat(f.input(:publish_at, :as => :time_picker))
        end
      )
      output_buffer.should have_tag "input[step='60']"
    end

    it "can be set from :input_html options" do
      concat(
        semantic_form_for(@new_post) do |f|
          concat(f.input(:publish_at, :as => :time_picker, :input_html => { :step => "3600" }))
        end
      )
      output_buffer.should have_tag "input[step='3600']"
    end

    describe "macros" do
      before do
        concat(
          semantic_form_for(@new_post) do |f|
            concat(f.input(:publish_at, :as => :date_picker, :input_html => { :step => step }))
          end
        )
      end

      context ":second" do
        let(:step) { :second }
        it "uses 1" do
          output_buffer.should have_tag "input[step='1']"
        end
      end

      context ":minute" do
        let(:step) { :minute }
        it "uses 60" do
          output_buffer.should have_tag "input[step='60']"
        end
      end

      context ":fifteen_minutes" do
        let(:step) { :fifteen_minutes }
        it "uses 900" do
          output_buffer.should have_tag "input[step='900']"
        end
      end

      context ":quarter_hour" do
        let(:step) { :quarter_hour }
        it "uses 900" do
          output_buffer.should have_tag "input[step='900']"
        end
      end

      context ":thirty_minutes" do
        let(:step) { :thirty_minutes }
        it "uses 1800" do
          output_buffer.should have_tag "input[step='1800']"
        end
      end

      context ":half_hour" do
        let(:step) { :half_hour }
        it "uses 1800" do
          output_buffer.should have_tag "input[step='1800']"
        end
      end

      context ":hour" do
        let(:step) { :hour }
        it "uses 3600" do
          output_buffer.should have_tag "input[step='3600']"
        end
      end

      context ":sixty_minutes" do
        let(:step) { :sixty_minutes }
        it "uses 3600" do
          output_buffer.should have_tag "input[step='3600']"
        end
      end

    end

  end

  describe "placeholder attribute" do

    it "will be omitted" do
      concat(
        semantic_form_for(@new_post) do |f|
          concat(f.input(:publish_at, :as => :time_picker))
        end
      )
      output_buffer.should_not have_tag "input[placeholder]"
    end

    it "can be set from :input_html options" do
      concat(
        semantic_form_for(@new_post) do |f|
          concat(f.input(:publish_at, :as => :time_picker, :input_html => { :placeholder => "HH:MM" }))
        end
      )
      output_buffer.should have_tag "input[placeholder='HH:MM']"
    end

    context "with i18n set" do
      before do
        ::I18n.backend.store_translations :en, :formtastic => { :placeholders => { :publish_at => 'HH:MM' }}
      end

      it "can be set with i18n" do
        with_config :i18n_lookups_by_default, true do
          concat(semantic_form_for(@new_post) do |builder|
            concat(builder.input(:publish_at, :as => :time_picker))
          end)
          output_buffer.should have_tag('input[@placeholder="HH:MM"]')
        end
      end

      it "can be set with input_html, trumping i18n" do
        with_config :i18n_lookups_by_default, true do
          concat(semantic_form_for(@new_post) do |builder|
            concat(builder.input(:publish_at, :as => :time_picker, :input_html => { :placeholder => "Something" }))
          end)
          output_buffer.should have_tag('input[@placeholder="Something"]')
        end
      end
    end

  end

  describe "when namespace is provided" do
    before do
      concat(semantic_form_for(@new_post, :namespace => "context2") do |builder|
        concat(builder.input(:publish_at, :as => :time_picker))
      end)
    end

    it_should_have_input_wrapper_with_id("context2_post_publish_at_input")
    it_should_have_label_and_input_with_id("context2_post_publish_at")
  end

  describe "when index is provided" do
    before do
      @output_buffer = ''
      mock_everything

      concat(semantic_form_for(@new_post) do |builder|
        concat(builder.fields_for(:author, :index => 3) do |author|
          concat(author.input(:created_at, :as => :time_picker))
        end)
      end)
    end

    it 'should index the id of the wrapper' do
      output_buffer.should have_tag("li#post_author_attributes_3_created_at_input")
    end

    it 'should index the id of the select tag' do
      output_buffer.should have_tag("input#post_author_attributes_3_created_at")
    end

    it 'should index the name of the select tag' do
      output_buffer.should have_tag("input[@name='post[author_attributes][3][created_at]']")
    end
  end

  describe "when required" do
    it "should add the required attribute to the input's html options" do
      with_config :use_required_attribute, true do
        concat(semantic_form_for(@new_post) do |builder|
          concat(builder.input(:publish_at, :as => :time_picker, :required => true))
        end)
        output_buffer.should have_tag("input[@required]")
      end
    end
  end

end


text:
class GURL;

namespace blink {
class WebElement;
class WebFrame;
class WebLocalFrame;
class WebNode;
class WebPlugin;
class WebURLRequest;
class WebURLResponse;
struct WebPluginParams;
}

namespace gfx {
class Range;
class Size;
}

namespace url {
class Origin;
}

namespace v8 {
template <typename T> class Local;
class Context;
class Isolate;
}

namespace content {
class ContextMenuClient;
class PluginInstanceThrottler;
class RenderView;
class ServiceRegistry;
struct ContextMenuParams;
struct WebPluginInfo;
struct WebPreferences;

// This interface wraps functionality, which is specific to frames, such as
// navigation. It provides communication with a corresponding RenderFrameHost
// in the browser process.
class CONTENT_EXPORT RenderFrame : public IPC::Listener,
                                   public IPC::Sender {
 public:
  // These numeric values are used in UMA logs; do not change them.
  enum PeripheralContentStatus {
    // Content is peripheral because it doesn't meet any of the below criteria.
    CONTENT_STATUS_PERIPHERAL = 0,
    // Content is essential because it's same-origin with the top-level frame.
    CONTENT_STATUS_ESSENTIAL_SAME_ORIGIN = 1,
    // Content is essential even though it's cross-origin, because it's large.
    CONTENT_STATUS_ESSENTIAL_CROSS_ORIGIN_BIG = 2,
    // Content is essential because there's large content from the same origin.
    CONTENT_STATUS_ESSENTIAL_CROSS_ORIGIN_WHITELISTED = 3,
    // Content is essential because it's tiny in size.
    CONTENT_STATUS_ESSENTIAL_CROSS_ORIGIN_TINY = 4,
    // Content is essential because it has an unknown size.
    CONTENT_STATUS_ESSENTIAL_UNKNOWN_SIZE = 5,
    // Must be last.
    CONTENT_STATUS_NUM_ITEMS
  };

  // Returns the RenderFrame given a WebFrame.
  static RenderFrame* FromWebFrame(blink::WebFrame* web_frame);

  // Returns the RenderFrame given a routing id.
  static RenderFrame* FromRoutingID(int routing_id);

  // Returns the RenderView associated with this frame.
  virtual RenderView* GetRenderView() = 0;

  // Get the routing ID of the frame.
  virtual int GetRoutingID() = 0;

  // Returns the associated WebFrame.
  virtual blink::WebLocalFrame* GetWebFrame() = 0;

   // Gets WebKit related preferences associated with this frame.
  virtual WebPreferences& GetWebkitPreferences() = 0;

  // Shows a context menu with the given information. The given client will
  // be called with the result.
  //
  // The request ID will be returned by this function. This is passed to the
  // client functions for identification.
  //
  // If the client is destroyed, CancelContextMenu() should be called with the
  // request ID returned by this function.
  //
  // Note: if you end up having clients outliving the RenderFrame, we should add
  // a CancelContextMenuCallback function that takes a request id.
  virtual int ShowContextMenu(ContextMenuClient* client,
                              const ContextMenuParams& params) = 0;

  // Cancels a context menu in the event that the client is destroyed before the
  // menu is closed.
  virtual void CancelContextMenu(int request_id) = 0;

  // Create a new NPAPI/Pepper plugin depending on |info|. Returns NULL if no
  // plugin was found. |throttler| may be empty.
  virtual blink::WebPlugin* CreatePlugin(
      blink::WebFrame* frame,
      const WebPluginInfo& info,
      const blink::WebPluginParams& params,
      std::unique_ptr<PluginInstanceThrottler> throttler) = 0;

  // The client should handle the navigation externally.
  virtual void LoadURLExternally(const blink::WebURLRequest& request,
                                 blink::WebNavigationPolicy policy) = 0;

  // Execute a string of JavaScript in this frame's context.
  virtual void ExecuteJavaScript(const base::string16& javascript) = 0;

  // Returns true if this is the main (top-level) frame.
  virtual bool IsMainFrame() = 0;

  // Return true if this frame is hidden.
  virtual bool IsHidden() = 0;

  // Returns the ServiceRegistry for this frame.
  virtual ServiceRegistry* GetServiceRegistry() = 0;

#if defined(ENABLE_PLUGINS)
  // Registers a plugin that has been marked peripheral. If the origin
  // whitelist is later updated and includes |content_origin|, then
  // |unthrottle_callback| will be called.
  virtual void RegisterPeripheralPlugin(
      const url::Origin& content_origin,
      const base::Closure& unthrottle_callback) = 0;

  // Returns the peripheral content heuristic decision.
  //
  // Power Saver is enabled for plugin content that are cross-origin and
  // heuristically determined to be not essential to the web page content.
  //
  // Plugin content is defined to be cross-origin when the plugin source's
  // origin differs from the top level frame's origin. For example:
  //  - Cross-origin:  a.com -> b.com/plugin.swf
  //  - Cross-origin:  a.com -> b.com/iframe.html -> b.com/plugin.swf
  //  - Same-origin:   a.com -> b.com/iframe-to-a.html -> a.com/plugin.swf
  //
  // |main_frame_origin| is the origin of the main frame.
  //
  // |content_origin| is the origin of the plugin content.
  //
  // |unobscured_size| are zoom and device scale independent logical pixels.
  virtual PeripheralContentStatus GetPeripheralContentStatus(
      const url::Origin& main_frame_origin,
      const url::Origin& content_origin,
      const gfx::Size& unobscured_size) const = 0;

  // Whitelists a |content_origin| so its content will never be throttled in
  // this RenderFrame. Whitelist is cleared by top level navigation.
  virtual void WhitelistContentOrigin(const url::Origin& content_origin) = 0;
#endif

  // Returns true if this frame is a FTP directory listing.
  virtual bool IsFTPDirectoryListing() = 0;

  // Attaches the browser plugin identified by |element_instance_id| to guest
  // content created by the embedder.
  virtual void AttachGuest(int element_instance_id) = 0;

  // Detaches the browser plugin identified by |element_instance_id| from guest
  // content created by the embedder.
  virtual void DetachGuest(int element_instance_id) = 0;

  // Notifies the browser of text selection changes made.
  virtual void SetSelectedText(const base::string16& selection_text,
                               size_t offset,
                               const gfx::Range& range) = 0;

  // Ensures that builtin mojo bindings modules are available in |context|.
  virtual void EnsureMojoBuiltinsAreAvailable(
      v8::Isolate* isolate,
      v8::Local<v8::Context> context) = 0;

  // Adds |message| to the DevTools console.
  virtual void AddMessageToConsole(ConsoleMessageLevel level,
                                   const std::string& message) = 0;

  // Whether or not this frame is using Lo-Fi.
  virtual bool IsUsingLoFi() const = 0;

  // Whether or not this frame is currently pasting.
  virtual bool IsPasting() const = 0;

 protected:
  ~RenderFrame() override {}

 private:
  // This interface should only be implemented inside content.
  friend class RenderFrameImpl;
  RenderFrame() {}
};

}  // namespace content

#endif  // CONTENT_PUBLIC_RENDERER_RENDER_FRAME_H_


text:
#region License

#endregion License

using System.Collections.Generic;

namespace Revalee.Client.RecurringTasks
{
	internal interface ITaskCollection
	{
		int Count { get; }

		IEnumerable<ConfiguredTask> Tasks { get; }

		bool TryGetTask(string identifier, out ConfiguredTask taskConfig);

		bool Add(ConfiguredTask taskConfig);

		bool Remove(string identifier);

		bool Remove(ConfiguredTask taskConfig);
	}
}


text:
managers=1
workers=2

# Stop machines
echo "======> Stoping $workers worker machines ...";
for node in $(seq 1 $workers);
do
	docker-machine stop worker$node;
	echo "======> Stoped worker$node machine ...";
done

echo "======> Stoping $managers manager machines ...";
for node in $(seq 1 $managers);
do
	docker-machine stop manager$node;
	echo "======> Stoped manager$node machine ...";
done

# remove machines
echo "======> Removing $workers worker machines ...";
for node in $(seq 1 $workers);
do
	docker-machine rm worker$node --force;
	echo "======> Removed worker$node machine ...";
done

echo "======> Removing $managers manager machines ...";
for node in $(seq 1 $managers);
do
	docker-machine rm manager$node --force;
	echo "======> Removed manager$node machine ...";
done

docker-machine ls


text:
datasciencecoursera
===================

For my coursera Data Science Courses


text:
from __future__ import annotations

import pathlib

import procrunner
import pytest

from dxtbx.serialize import load

from dials.array_family import flex
from dials.command_line.ssx_integrate import run_integration, working_phil
from dials.util.options import ArgumentParser

# Note that tests are grouped and run serially, to stop many processes trying to
# extract data from images at same time, which appears to lead to race
# conditions in some CI jobs.

@pytest.mark.xdist_group(name="group1")
def test_ssx_integrate_fullprocess(dials_data, tmp_path):
    # Download data set and the internally referenced images
    ssx = dials_data("cunir_serial_processed", pathlib=True)
    dials_data("cunir_serial", pathlib=True)
    pathlib.Path.mkdir(tmp_path / "nuggets")
    result = procrunner.run(
        [
            "dials.ssx_integrate",
            ssx / "indexed.refl",
            ssx / "indexed.expt",
            "nproc=1",
            "batch_size=3",
            "output.json=data.json",
            "output.nuggets=nuggets",
            "algorithm=stills",
        ],
        working_directory=tmp_path,
    )
    assert not result.returncode and not result.stderr
    assert tmp_path.joinpath("integrated_1.refl").is_file()
    assert tmp_path.joinpath("integrated_1.expt").is_file()
    assert tmp_path.joinpath("integrated_2.refl").is_file()
    assert tmp_path.joinpath("integrated_2.expt").is_file()
    assert tmp_path.joinpath("dials.ssx_integrate.html").is_file()
    assert tmp_path.joinpath("data.json").is_file()
    for i in range(1, 6):
        assert tmp_path.joinpath(f"nuggets/nugget_integrated_{i}.json").is_file()

@pytest.mark.xdist_group(name="group1")
def test_ssx_integrate_fullprocess_ellipsoid(dials_data, tmp_path):
    # Download data set and the internally referenced images
    ssx = dials_data("cunir_serial_processed", pathlib=True)
    dials_data("cunir_serial", pathlib=True)

    expts = load.experiment_list(ssx / "indexed.expt", check_format=False)
    expts[3:4].as_file(tmp_path / "single.expt")
    refls = flex.reflection_table.from_file(ssx / "indexed.refl")
    refls = refls.select_on_experiment_identifiers([expts[3].identifier])
    refls.as_file(tmp_path / "single.refl")

    result = procrunner.run(
        [
            "dials.ssx_integrate",
            tmp_path / "single.refl",
            tmp_path / "single.expt",
            "nproc=1",
            "algorithm=ellipsoid",
            "n_macro_cycles=2",
        ],
        working_directory=tmp_path,
    )
    assert not result.returncode and not result.stderr
    assert tmp_path.joinpath("integrated_1.refl").is_file()
    assert tmp_path.joinpath("integrated_1.expt").is_file()
    assert tmp_path.joinpath("dials.ssx_integrate.html").is_file()
    expts = load.experiment_list(tmp_path / "integrated_1.expt", check_format=False)
    mosaicity = expts[0].profile.mosaicity()
    assert mosaicity["radial"] < 0.0250 and mosaicity["radial"] > 0.0240
    assert mosaicity["angular_0"] < 0.0265 and mosaicity["angular_0"] > 0.0255
    assert mosaicity["angular_1"] < 0.006 and mosaicity["angular_1"] > 0.004

@pytest.mark.parametrize("algorithm,expected_n_refls", [("stills", 614)])
@pytest.mark.xdist_group(name="group1")
def test_ssx_integrate_algorithms(dials_data, algorithm, expected_n_refls):
    # Download data set and the internally referenced images
    ssx = dials_data("cunir_serial_processed", pathlib=True)
    dials_data("cunir_serial", pathlib=True)

    indexed_refl = flex.reflection_table.from_file(
        ssx / "indexed.refl"
    ).split_by_experiment_id()
    indexed_expts = load.experiment_list(ssx / "indexed.expt", check_format=True)

    parser = ArgumentParser(phil=working_phil, check_format=False)
    params, _ = parser.parse_args(args=[], quick_parse=True)

    params.algorithm = algorithm
    params.nproc = 1
    params.image_range = "1:2"

    results = list(run_integration(indexed_refl, indexed_expts, params))
    assert len(results) == 1  # only one batch expected
    experiments = results[0][0]
    reflections = results[0][1]

    assert len(experiments) == 2
    assert len(reflections) == pytest.approx(expected_n_refls, abs=9)


text:
<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

	<context:property-placeholder/>

	<bean id="actionEnter" class="com.piggsoft.ueditor.ActionEnter"
		scope="prototype">
		<property name="configManager" ref="configManager"></property>
		<property name="imageHunter" ref="imageHunter"></property>
		<property name="uploader" ref="uploader"></property>
		<property name="listManager" ref="listManager"></property>
	</bean>

	<bean id="uploader" class="com.piggsoft.ueditor.upload.Uploader">
		<property name="base64Uploader" ref="base64Uploader"></property>
		<property name="binaryUploader" ref="binaryUploader"></property>
	</bean>

	<bean id="configManager" class="com.piggsoft.ueditor.ConfigManager" scope="prototype">
		<property name="originalPath" value="classpath:config.json"></property>
		<property name="rootPath" value="${ueditor-piggsoft-rootPath}"></property>
	</bean>

	<bean id="listManager" class="com.piggsoft.ueditor.hunter.ListManager"></bean>

	<bean id="imageHunter" class="com.piggsoft.ueditor.hunter.ImageHunter">
		<property name="storageManager" ref="storageManager"></property>
	</bean>

	<bean id="base64Uploader" class="com.piggsoft.ueditor.upload.Base64Uploader">
		<property name="storageManager" ref="storageManager"></property>
	</bean>
	<bean id="binaryUploader" class="com.piggsoft.ueditor.upload.BinaryUploader">
		<property name="storageManager" ref="storageManager"></property>
	</bean>

	<bean id="storageManager" class="com.piggsoft.ueditor.upload.StorageManager">
		<property name="storageSuccessCallBack" ref="storageSuccessCallBack"></property>
	</bean>

	<bean id="storageSuccessCallBack" class="com.piggsoft.ueditor.callback.DefaultStorageSuccessCallBack"></bean>

</beans>


text:
// Copyright 2017 The Nomulus Authors. All Rights Reserved.
//
// 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.

package google.registry.testing;

import com.googlecode.objectify.Key;
import com.googlecode.objectify.annotation.Entity;
import com.googlecode.objectify.annotation.Id;
import google.registry.model.ImmutableObject;
import google.registry.model.annotations.DeleteAfterMigration;
import google.registry.model.annotations.VirtualEntity;
import google.registry.persistence.VKey;

/** A test model object that can be persisted in any entity group. */
@DeleteAfterMigration
@Entity
public class TestObject extends ImmutableObject {

  @Id @javax.persistence.Id String id;

  String field;

  public String getId() {
    return id;
  }

  public String getField() {
    return field;
  }

  public VKey<TestObject> key() {
    return VKey.create(TestObject.class, id);
  }

  public static TestObject create(String id) {
    return create(id, null);
  }

  public static TestObject create(String id, String field) {
    TestObject instance = new TestObject();
    instance.id = id;
    instance.field = field;
    return instance;
  }

  /** A test @VirtualEntity model object, which should not be persisted. */
  @Entity
  @VirtualEntity
  public static class TestVirtualObject extends ImmutableObject {

    @Id String id;

    /**
     * Expose a factory method for testing saves of virtual entities; in real life this would never
     * be needed for an actual @VirtualEntity.
     */
    public static TestVirtualObject create(String id) {
      TestVirtualObject instance = new TestVirtualObject();
      instance.id = id;
      return instance;
    }

    public static Key<TestVirtualObject> createKey(String id) {
      return Key.create(TestVirtualObject.class, id);
    }
  }
}


text:
#include <serenity.h>

static inline char*
sn_keyof(sndb *db, char *key, int keysize, int *rsize)
{
	if (snlikely(db->keytype == SN_KEYSTRING)) {
		*rsize = keysize;
		return key;
	}
	static uint32_t u32;
	static uint64_t u64;
	switch (db->keytype) {
	case SN_KEYU32:
		u32 = sn_decode_number(key, key + keysize);
		*rsize = sizeof(uint32_t);
		return (char*)&u32;
	case SN_KEYU64:
		u64 = sn_decode_number(key, key + keysize);
		*rsize = sizeof(uint64_t);
		return (char*)&u64;
	default: break;
	}
	assert(0);
	return NULL;
}

int sn_execute(sn *s, snclient *c, snrequest *r)
{
	char *error;
	void *o;
	sndb *db = sn_databaseof(&s->storage, c->db);
	void *database = db->db;
	void *dest = database;
	if (c->transaction)
		dest = c->transaction;

	int keysize;
	char *key;
	int valuesize;
	char *value;

	int rc;
	switch (r->cmd) {
	case SN_SET: {
		key = sn_keyof(db, r->key, r->keysize, &keysize);
		o = sp_object(database);
		sp_setstring(o, "key", key, keysize);
		sp_setstring(o, "value", r->value, r->valuesize);
		rc = sp_set(dest, o);
		if (snunlikely(rc == -1)) {
			error = sn_storageerror(s->storage.env);
			sn_encode_errorf(&c->result, "STORAGE ERROR %s", error);
			free(error);
			return -1;
		}
		return sn_encode_stringf(&c->result, "OK");
	}
	case SN_DEL: {
		key = sn_keyof(db, r->key, r->keysize, &keysize);
		void *o = sp_object(database);
		sp_setstring(o, "key", key, keysize);
		rc = sp_delete(dest, o);
		if (snunlikely(rc == -1)) {
			error = sn_storageerror(s->storage.env);
			sn_encode_errorf(&c->result, "STORAGE ERROR %s", error);
			free(error);
			return -1;
		}
		return sn_encode_stringf(&c->result, "OK");
	}
	case SN_GET: {
		key = sn_keyof(db, r->key, r->keysize, &keysize);
		o = sp_object(database);
		sp_setstring(o, "key", key, keysize);
		o = sp_get(dest, o);
		if (o == NULL)
			return sn_encode_nil(&c->result);
		value = sp_getstring(o, "value", &valuesize);
		rc = sn_encode_bin(&c->result, value, valuesize);
		sp_destroy(o);
		return rc;
	}
	case SN_EXISTS: {
		key = sn_keyof(db, r->key, r->keysize, &keysize);
		o = sp_object(database);
		sp_setstring(o, "key", key, keysize);
		o = sp_get(dest, o);
		if (o == NULL)
			return sn_encode_int(&c->result, 0);
		sp_destroy(o);
		return sn_encode_int(&c->result, 1);
	}
	case SN_CURSOR: {
		sncursor *cur = sn_cursornew(&c->cursors);
		if (snunlikely(cur == NULL))
			return sn_encode_errorf(&c->result, "ERROR out-of-memory");
		o = sp_object(database);
		sp_setstring(o, "order", r->key, r->keysize);
		if (r->value) {
			key = sn_keyof(db, r->value, r->valuesize, &keysize);
			sp_setstring(o, "key", key, keysize);
		}
		cur->c = sp_cursor(database, o);
		if (snunlikely(cur->c == NULL)) {
			sn_cursorfree(&c->cursors, cur);
			error = sn_storageerror(s->storage.env);
			sn_encode_errorf(&c->result, "ERROR failed to create cursor %s", error);
			free(error);
			return -1;
		}
		sn_cursorattach(&c->cursors, cur);
		return sn_encode_int(&c->result, cur->id);
	}
	case SN_NEXT: {
		int id = sn_decode_number(r->key, r->key + r->keysize);
		sncursor *cur = sn_cursormatch(&c->cursors, id);
		if (snunlikely(cur == NULL))
			return sn_encode_errorf(&c->result, "ERROR failed to match cursor '%d'", id);
		void *o = sp_get(cur->c, NULL);
		if (o == NULL) {
			sn_cursorfree(&c->cursors, cur);
			return sn_encode_nil(&c->result);
		}
		rc = sn_encode_array(&c->result, 2);
		int keysize;
		int valuesize;
		char *key = sp_getstring(o, "key", &keysize);
		char *value = sp_getstring(o, "value", &valuesize);
		char keysz[32];
		if (db->keytype == SN_KEYU32) {
			keysize = snprintf(keysz, sizeof(keysz), "%"PRIu32, *(uint32_t*)key);
			rc = sn_encode_bin(&c->result, keysz, keysize);
		} else
		if (db->keytype == SN_KEYU64) {
			keysize = snprintf(keysz, sizeof(keysz), "%"PRIu64, *(uint64_t*)key);
			rc = sn_encode_bin(&c->result, keysz, keysize);
		} else {
			rc = sn_encode_bin(&c->result, key, keysize);
		}
		rc = sn_encode_bin(&c->result, value, valuesize);
		sp_destroy(o);
		return 0;
	}
	case SN_CLOSE: {
		int id = sn_decode_number(r->key, r->key + r->keysize);
		sncursor *cur = sn_cursormatch(&c->cursors, id);
		if (snunlikely(cur == NULL))
			return sn_encode_errorf(&c->result, "ERROR failed to match cursor '%d'", id);
		sn_cursorfree(&c->cursors, cur);
		return sn_encode_stringf(&c->result, "OK");
	}
	case SN_SELECT: {
		if (snunlikely(r->keysize == 0))
			return sn_encode_errorf(&c->result, "ERROR bad select argument");
		int id = 0;
		if (! isdigit(r->key[0])) {
			id = sn_storagematch(&s->storage, r->key, r->keysize);
			if (snunlikely(id == -1)) {
				return sn_encode_errorf(&c->result, "ERROR database '%.*s' not found",
				                        r->keysize, r->key);
			}
		} else {
			id = sn_decode_number(r->key, r->key + r->keysize);
		}
		if (snunlikely(id >= s->storage.count))
			return sn_encode_errorf(&c->result, "ERROR database does not exists (databases %d)",
			                        s->storage.count);
		c->db = id;
		return sn_encode_stringf(&c->result, "OK");
	}
	case SN_BEGIN: {
		if (c->transaction)
			return sn_encode_errorf(&c->result, "ERROR transaction is in progress");
		c->transaction = sp_begin(s->storage.env);
		if (c->transaction == NULL) {
			error = sn_storageerror(s->storage.env);
			sn_encode_errorf(&c->result, "STORAGE ERROR %s", error);
			free(error);
			return -1;
		}
		return sn_encode_stringf(&c->result, "OK");
	}
	case SN_COMMIT: {
		if (c->transaction == NULL)
			return sn_encode_errorf(&c->result, "ERROR not in transaction");
		rc = sp_commit(c->transaction);
		switch (rc) {
		case -1:
			error = sn_storageerror(s->storage.env);
			sn_encode_errorf(&c->result, "STORAGE ERROR %s", error);
			free(error);
			c->transaction = NULL;
			return -1;
		case  2:
			sp_destroy(c->transaction);
		case  1:
			c->transaction = NULL;
			return sn_encode_errorf(&c->result, "ERROR rollback by conflict");
		}
		c->transaction = NULL;
		return sn_encode_stringf(&c->result, "OK");
	}
	case SN_ROLLBACK: {
		if (c->transaction == NULL)
			return sn_encode_errorf(&c->result, "ERROR not in transaction");
		rc = sp_destroy(c->transaction);
		switch (rc) {
		case -1:
			error = sn_storageerror(s->storage.env);
			sn_encode_errorf(&c->result, "STORAGE ERROR %s", error);
			free(error);
			c->transaction = NULL;
			return -1;
		}
		c->transaction = NULL;
		return sn_encode_stringf(&c->result, "OK");
	}
	case SN_CALL: {
		snproc *proc = sn_procmatch(&s->procs, r->key, r->keysize);
		if (proc == NULL) {
			sn_encode_errorf(&c->result, "unknown procedure '%.*s'",
			                 r->keysize, r->key);
			return -1;
		}
		return proc->f(c, r->value, r->valuesize);
	}
	case SN_PING:
		return sn_encode_stringf(&c->result, "PONG");
	case SN_INFO: {
		snbuf info;
		sn_bufinit(&info);
		char desc[] = "# Storage info\n";
		sn_bufadd(&info, desc, sizeof(desc) - 1);
		sn_storageinfo(&s->storage, &info);
		rc = sn_encode_bin(&c->result, info.s, sn_bufused(&info));
		sn_buffree(&info);
		return rc;
	}
	case SN_SHUTDOWN:
		sn_stop(s);
		return sn_encode_stringf(&c->result, "OK");
	}
	return sn_encode_errorf(&c->result, "ERROR bad request");
}