
views.text = function( elem, vals ) {
    for( var v in vals ) {
      var val = vals[v];
      if( null !== val && undefined !== val ) {
        var valelem = elem.find(v);
        _.isFunction(val) ? val(valelem) : valelem.text( ''+val);
      }
    }
  }


views.showif = function(obj,spec) {
    if( spec ) { 
      obj.__showif = spec
    }
    else if( obj.__showif ) {
      for( var en in obj.__showif ) {
        var elem = obj[en]
        if( elem ) {
          var show = (obj.__showif[en])()
          if( show ) {
            util.show(elem)
          }
          else {
            util.hide(elem)
          }
        }
      }
    }
}


  Backbone.View.prototype.renderwhen = function( model, prop, val ) {
    var self = this
    model.when_equal(prop,val, function(equal,curval) {
      equal ? (self.render && self.render()) : (self.hide && self.hide())
    })
  }

  Backbone.View.prototype.renderonchange = function( model, prop ) {
    var self = this
    model.bind('change:'+prop,function(){
      self.render && self.render()
    })
  }

  Backbone.Model.prototype.when_equal = function(prop,val,cb) {
    var self = this
    self.bind('change:'+prop, function(){
      var curval = self.get(prop)
      cb( curval === val, curval )
    })
  }



views.s3imgurl = function( imgurl, code ) {
  var imageName = imgurl//.split("images/")[1];
  return "http://i1.businesspost.ie/"+(code||'phf')+'c_'+imageName
}


function SpinPane( elem, width, height ) {
  var self = this
  
  var spin_pane = $('<div>').addClass('spinpane').css({width:width,height:height})
  var spin_elem = $('<div>').addClass('spin')
  var spinner = new Spinner(spin_opts)
  var spinning = false

  spin_pane.append(spin_elem)
  elem.append( spin_pane )

  self.start = function() {
    if( !spinning ) {
      spinner.spin( spin_elem[0] || util.die('91f0ed') )
      util.show(spin_pane)
      spinning = true
    }
  }

  self.stop = function() {
    util.hide(spin_pane)
    if( spinning ) {
      spinner.stop()
      spinning = false
    }
  }

  self.size = function(width,height) {
    spin_pane.css({width:width,height:height})
  }
}


views.common = function() {

  views.makepage = function( basic ) {
    basic.options.hash     = basic.options.hash     || basic.name
    basic.options.pagetype = basic.options.pagetype || basic.name
  }


  // customfunc: return true to skip item
  views.list = function( listsel, itemsel, insertmap, customfunc, clickfunc ) {
    var list_elem = $(listsel)
    var item_elem = $(itemsel).clone()

    function identity(val){return val}
    function empty(val){return null === val || undefined === val || '' === val }

    var out = {
      elem:list_elem,
      render: function( list, cb ) {
        if( !list ) { return; }

        list_elem.empty()
        
        var val,state = {}

        for( var i = 0; i < list.length; i++ ) {
          var item = list[i]
          if( null === item || undefined === item ) continue;

          var elem = item_elem.clone()
          util.show(elem)

          for( var sel in insertmap ) {
            var propdef = insertmap[sel]
            var selelem = elem.find(sel)

            if( 'string' === typeof(propdef) ) {
              var prop = propdef
              val = item[prop]
              selelem.text(val)
            }
            else if ( 'function' === typeof(propdef) ) {
              var propfunc = propdef
              val = propfunc( item, selelem, i, list )
              if( null !== val ) {
                selelem.html(val)
              }
            }
            else {
              val = item[propdef.val]

              if( 'hide' === propdef.ifempty && empty(val) ) {
                selelem.hide()
              }
              else {
                if( propdef.setattr ) {
                  if( 'string' === typeof(propdef.setattr) ) {
                    selelem.attr(propdef.setattr,val)
                  }
                  else {
                    var attr = propdef.setattr.name
                    var custom = propdef.setattr.custom || identity;
                    selelem.attr(propdef.setattr.name,custom(val))
                  }
                }
                else {
                  selelem.text(val)
                }
              }
            }

          }

          var insert = customfunc ? !customfunc(item,elem,i,list,state) : true
          if( insert ) {
            list_elem.append(elem)
            var cf = clickfunc && clickfunc(item,elem,i,list,state)
            cf && elem.bind(C.tap,cf)
          }
        }

        cb && setTimeout(cb,25)
      }
    }

    return out
  }



  views.slidedown = {
    show: function( el ) {
      el.css({zIndex:9200,position:'absolute',top:136})
      var content = el.find('div.content')

      var overlay = $('<div>').css({position:'absolute',top:0,left:0,zIndex:9100,
                                    width:'100%',
                                    height:'100%'
                                    //,opacity:0.2, backgroundColor:'green'
                                   })

      el.data('overlay',overlay)

      overlay.bind(C.tap,function(){
        views.slidedown.hide(el)
      })

      $('body').append(overlay)

      el.find('a.close').bind(C.tap,function(){
        views.slidedown.hide(el)
      })

      util.show(el)

      var h = content.height()

      Firmin.translateY( content[0], -1*h).translateY( 0, '1s')
    },

    hide: function(el) {
      var content = el.find('div.content')

      var overlay = el.data('overlay',overlay)
      overlay && ( overlay.remove() && el.data('overlay',null) )

      var h = content.height()

      Firmin.translateY( content[0], -1*h,'1s',function(){
        util.hide(el)
      })
    }
  }


  views.markpremium = function(h,type) {
    if( navigator.device ) {
      h = '<span style="color:#00864c">&#10029;</span>&nbsp;'+h
    }
    else {
      var starstyle = 'background: url(/img/icon_star.png) no-repeat; background-position:0px 0px;'
      if( 'small' === type ) {
        starstyle = 'background: url(/img/icon_smallstar.png) no-repeat; background-position:0px 0px;'
      }
      h = '<span style="'+starstyle+'">&nbsp;&nbsp;&nbsp;&nbsp;</span>'+h
    }
    return h
  }


  views.articlelist = {
    // args: model, el, item_tm
    initialize: function() { 
      var self=this;
      _.bindAll(this,'render','hide')

      self.listelem = $(self.options.listelem)

      self.options.model.bind('article-list-update',function(){
        self.render()
      })

      self.showstory = {}

      self.articlelist = views.list(
        self.options.listelem,
        self.options.itemelem,
        {
          'h4': function(item){
            var cat = self.options.catmodel.get('cat')
            var subcat = self.options.catmodel.get('subcat')
            var markpremium = true // !('Home'==cat&&(''==subcat||'News'==subcat))

            var h = item.h
            if( markpremium && 'daily' !== item.ty ) {
              h = views.markpremium(h,self.options.smallstar&&'small')
            }

            return h
          },
          'h3': 'c',
          'p.subcat': function(item){
            var subcat = self.options.catmodel.get('subcat')
            return ('' === subcat || null === subcat) ? item.sc : ''
          },
          'p.deck': function(item){
            var maxchars = self.options.maxchars || 188, val = item.d
            if( maxchars < val.length ) {
              val = val.substring(0,maxchars)+'&hellip;'
            }
            return val
          },
          'p.meta': function(item){
            if( item.pub ) {
              var d = item.pub

              if( _.isString(item.pub) ) {
                var dstr = item.pub.replace('.000','')
                d = Date.parseExact(dstr,'yyyy-MM-ddTHH:mm:ssZ')                
              }

              var now = new Date()
              var isToday = d.getYear()===now.getYear()&&d.getMonth()===now.getMonth()&&d.getDate()===now.getDate()

              var format = self.options.isSearch ? 'datetime' : 'daily' === item.ty ? (isToday ? 'time' : 'datetime') : '';
              return app.model.articlestore.formatDate(d,format)+' by '+item.aut
            }
            else { return '' }
          },
          'img': {val:'img',ifempty:'hide',
                  setattr:{
                    name:'src',
                    custom:function(imgurl){return views.s3imgurl(imgurl,self.options.imgcode)}
                  }}
        },

        function(item,elem,i,list,state) {
          var cat = self.options.catmodel.get('cat')
          elem.find('p.subcat').attr('data-cat',cat)
          self.onitem && self.onitem(item,elem,i)

          var edition = app.model.edition.get('code')
          var ignore = false

          if( 'daily'==edition || self.options.isSearch ) {
            ignore = !( self.options.maxcount ? i < self.options.maxcount : true )
          }

          state.hmap = state.hmap || {}
          if( state.hmap[item.h] ) {
            ignore = true
          }
          else {
            state.hmap[item.h]=true
          }

          return ignore
        },

        function(item,elem,i,list) {
          var active_elem = elem
          var div_story = elem.find('div.story')
          if( div_story[0] ) {
            active_elem = div_story
          }

          self.showstory[item.sid] = new views.ArticleInfoView({
            el:active_elem,
            sid:item.sid,
            pub:item.pub,
            type:item.ty,
            list:list,
            index:i,
            listview:self,
            whence:self.options.name||'frontarticles',
            custom:self.options.articlecustom&&self.options.articlecustom(item,elem,i,list)
          })
        }
      )
    },

    render: function() { 
      var self=this;

      if( self.options.pagetype ) {
        var pagetype = app.model.page.get('type')
        if( self.options.pagetype !== pagetype ) return;
      }

      var arts = self.options.model.get('article_list')

      if( self.options.omit ) {
        var omit = _.isArray(self.options.omit) ? self.options.omit : [self.options.omit] 
        for( var i = 0; i < omit.length; i++ ) {
          var j = omit[i]
          if( j < 0 ) { j = arts.length + j }
          if( 0 <= j && j < arts.length ) {
            arts.splice(j,1)
          }
        }
      }

      self.showstory = {}
      self.articlelist.render(arts, function() {
        util.tick(function(){
          self.options.model.trigger('article-list-update-done')

          var show = true
          if( self.options.pagetype ) {
            var pagetype = app.model.page.get('type')
            show = pagetype === self.options.pagetype
          }

          if( show ) {
            util.show( self.listelem )
          }
        })
      })
    },

    hide: function() {
      var self=this;
      util.hide( self.listelem )
    }
  }



  views.Basic = Backbone.View.extend({
    
    initialize: function() {
      _.bindAll(this,'render','show','hide','page')
      var self=this;

      self.name    = self.options.name || self.name
      self.visible = self.options.visible || false
      self.dirty = true

      self.prefix = self.options.prefix || self.prefix
      self.selprefix = self.prefix+'_'+self.name

      self.el = (self.el.jquery && self.el.attr('id') && self.el) || $('#'+self.selprefix)

      self.init_impl && self.init_impl()
    },

    // call to render if visible
    render: function(modelname,eventname) {
      var self=this;

      var do_render = self.visible && ( self.dirty || (eventname && slang.startsWith(eventname,'change') ) )

      if( do_render ) {
        self.dirty = (self.render_impl && self.render_impl()) || false
      }
    },

    // call to render and make visible
    show: function( force, mark ) {
      var self=this;

      var do_show = force || !self.visible

      if( do_show ) {
        self.visible = true

        self.render()

        if( self.preshow ) {
          self.preshow()
        }

        if( self.show_impl ) {
          self.show_impl( mark )
        }
        else {
          self.el && util.show(self.el)
        }
      }

      return false
    },

    hide: function( mark ) {
      var self=this;

      var do_hide = self.visible

      if( do_hide ) {
        self.visible = false
        if( self.hide_impl ) {
          self.hide_impl( mark )
        }
        else {
          self.el && util.hide(self.el)
        }
      }
    },

    // call on page transition events
    page: function() {
      var self=this;
      var type = app.model.page.get('type')

      if( self.options.pagetype === type || 
          ( 'object'==typeof(self.options.pagetype) && self.options.pagetype[type] )
        ) 
      {
        self.show()
        
        var hash = (self.hash && ('function'==typeof(self.hash) ? self.hash() : self.hash)) || self.options.hash
        if( hash ) {
          app.navigate('#!'+hash)
        }

        window.scrollTo(0,0)
      }
      else {
        self.hide()
      }
    }
  })



  // FIX rename to StoryShow
  views.ArticleInfoView = Backbone.View.extend({
    initialize: function() {
      _.bindAll(this,'showArticle','sendToPurchase')
      var self=this;
      
      self.el = self.options.el
      if( self.el ) {
        self.el.bind(C.tap,self.showArticle)
      }

      self.evsuffix = (self.options.whence||'frontarticles')+':'+self.options.sid
    },

    showArticle: function() {
      var self=this;
      app.chartaca.fire('story-open:'+self.evsuffix)

      if( mode.touch ) {
        util.flash(self.el,{backgroundColor:'#00864c'},{backgroundColor:'transparent'})
      }

      function display_article() {
        util.tick(function(){
          app.model.page.set({artid:self.options.sid})
          app.model.page.set({type:'article'})
          if( self.options.custom ) {
            self.options.custom(self.options.sid)
          }
          if( app.articleview ) {
            app.articleview.render(self,'article-select')
          }

          app.chartaca.fire('story-view:'+self.evsuffix)
        })        
      }

      if( 'newspaper' === self.options.type ) {
        if( self.options.pub ) {

          if( _.isString(self.options.pub) ) {
            var dstr = self.options.pub.replace('.000','')
            self.options.pub = Date.parseExact(dstr,'yyyy-MM-ddTHH:mm:ssZ')                
          }

          if( app.model.user.access().access(self.options.pub,'article-select') ) {
            app.chartaca.fire('story-premium-view:'+self.evsuffix)
            display_article()
          }
          else {
            app.chartaca.fire('story-premium-noaccess:'+self.evsuffix)
            self.sendToPurchase(self.options.sid,self.options.pub)
          }
        }
        else display_article()
      }
      else {
        display_article()
      }

      app.admanager && app.admanager.show()
    },

    sendToPurchase: function(sid,pub) {
      var self=this;
      if( 'mob' === mode.name ) {
        app.model.purchase.begin({type:'article',sid:sid})
      }
      else {
        store.set('jump',{type:'article',sid:sid})
        var purchase = {sid:sid,pub:pub}
        store.set('purchase',purchase)
        
        app.model.page.set({purchase:purchase})
        app.model.page.set({type:'purchase'})
        if( app.view.purchase && app.view.purchase.scrollup ) {
          app.view.purchase.scrollup()
        }
      }
    }

  })


  views.ColView = Backbone.View.extend({
    className: 'article_col',

    items: new ColItemList(),
    pos:0,

    initialize: function() {
      _.bindAll(this,'render','setItems','clean','hide','empty')
      this.el = $(this.el)

      this.blocks = $('<div>').addClass('blocks')
      this.el.append(this.blocks)

      this.articlelayout = this.options.articlelayout
      this.pos = this.options.pos || 0

      this.articleview = this.options.articleview || app.model.articleview
    },


    render: function() {
      var own = this

      this.hidden = false
      this.el.css({display:'block'})

      this.clean()

      var w = this.articlelayout.get('colwidth')
      var h = this.articlelayout.get('colheight')
      var webcols = this.articlelayout.get('webcols')

      if( 0 < h ) {
        this.el.css({height:h+'px'})
      }

      if( !webcols ) {
        this.el.css({width:w+'px'});
      }

      if( mode.touch ) {
        this.el.css({overflow:'hidden', 'float':'left'})
      }


      //this.divider.hide()//css({height:(h-C.len2)+'px',left:(w-1)+'px'})
      
      var done = true
      var th = C.len;
      var items = (this.items && this.items.models) || []

      var colsize = this.articlelayout.get('colsize')
      var rightmostmod = colsize-1
      if( (this.pos % colsize) === rightmostmod && 0 !== this.pos && 3 < items.length ) {
        var aditem = new models.ColItem({type:'ad'})
        //items.unshift(aditem)
      }

      var textsize = (app.model.settings && app.model.settings.get('textsize')) || 5
      var old_textsize = (app.model.settings && app.model.settings.get('old_textsize')) || 11

      var pcount = 0;
      var firstpara = true

      for( var i = 0; i < items.length; i++ ) {
        var item = items[i]

        var p = $('<p>')

        var type = item.get('type')

        if( 'para' === type || !type ) {
          var text = item.get('text')
          var html = item.get('html')

          var content = html||text

          if( _.isString(content) ) {
            p = $('<div class="para">'+content+'</div>')            

            if( 0 === own.pos && firstpara ) {
              p.addClass('firstpara')
              firstpara = false
            }
          }
        }
        else if( 'head' === type ) {
          p = $('<div>').addClass('article_head')

          var title = item.get('title')
          p.append( $('<h2>').text(title) )

          p.append( $('<p>').addClass('article_meta').text(item.get('meta')) )

          var img = item.get('img')
          if( img ) {
            var imgurl = views.s3imgurl(img,'mac')
            p.append( $('<img>').addClass('article_img').attr('src',imgurl) )

            var ic = item.get('ic')
            if( _.isString(ic) ) {
              p.append($('<p>').addClass('image_caption').css({display:'block'}).text(ic))
            }
          }
        }
        else if( 'div' === type ) {
          p = $('<div>').html( item.get('div') ).addClass( item.get('class') )
          var bindfunc = item.get('bind')
          if( bindfunc ) {
            p.bind(C.quicktap,bindfunc)
          }
        }
        else if( 'ad' === type ) {
          p = $('<div>').addClass('article_ad')
          p.append( $('<p>').addClass('article_ad_img').append('<img src="img/adbox.gif">') )
        }
        else if( 'tail' === type ) {
          
          if( item.get('text') === "xshare" && !mode.touch ) {
/* DEL
            p = $('<div>').addClass('share').html(
              ''
+'<!-- AddThis Button BEGIN -->'
+'<div class="addthis_toolbox addthis_default_style ">'
+'<a class="addthis_button_tw]itter"></a>'
+'<a class="addthis_button_facebook"></a>'
+'<a class="addthis_button_linkedin"></a>'
+'<a class="addthis_button_email"></a>'
+'<a class="addthis_button_compact"></a>'
+'<a class="addthis_counter addthis_bubble_style"></a>'
+'</div>'
+'<script type="text/javascript" src="http://s7.addthis.com/js/250/addthis_widget.js#pubid=ra-4e6801ce03211d64"></script>'
+'<!-- AddThis Button END -->')

*/
          }

          // FIX: load async
          else if( item.get('text') === "xsimilar" ) {
            var similarHtml = "<h2>Similar Articles</h2>";
            for (var similarIndex in this.similar) {
              similarHtml += "<div><a href='/article/" + this.similar[similarIndex].sid + "'>" + this.similar[similarIndex].d.substring(0, 45) + "..." + "</a></div>";
            }
            p = $('<div>').addClass('article_tail')//.css('height',(h-40-20)+'px');
            p.append( $('<p>').addClass('article_tail_filler').html(similarHtml));
          }
          else {
            //share discover etc...
            p = $('<div>').addClass('article_tail')//.css('height',(h-40-20)+'px')
            p.append( $('<p>').addClass('article_tail_filler').text("") )
          }
        }


        pcount++
        this.blocks.append(p)

        var ph = p.height()
        th += ph + C.len

        //if( confirm(h+' < '+th+' pc='+pcount+', i='+i+' pos='+this.pos+' '+items.length) ) return;

        //var newcol = h < th


        var newcol = 
          mode.touch ? h < th && -1 !== h && 1 < pcount : false
          //webcols ? (0===this.pos&&(pcount==(2+Math.floor(items.length/2)))) : false


        if( newcol ) {
          p.remove()
          th -= ph
          done = false
          own.articleview.flowcol(this.pos+1,new ColItemList(_.rest(items,i)))
          break;
        }
      }

      if( done ) {
        //var fill = this.pos % this.articlelayout.get('colsize')
        this.articlelayout.trigger('flowend',this.pos)
      }
    },


    setItems: function(items) {
      this.items = items
    },

    setSimilar: function(similar) {
      this.similar = similar;
    },


    clean: function() {
      var kids = this.blocks.children()
      kids && kids.remove()
    },


    hide: function() {
      this.hidden = true
      this.el.css({display:'none'})
    },

    empty: function() {
      this.el.empty()
    }    
  })


  views.Search = views.Basic.extend({
    hash:'search',
    init_impl: function() {
      _.bindAll(this,'render_impl','spinup','spindown','query','scrollup')
      var self=this;

      self.el = $('#'+self.prefix+'_search_results')

      self.name = self.name || 'search'

      self.pagecount = 0
      self.maxcount = 24

      self.elem = {
        text:  $('#'+self.prefix+'_search_text'),
        btn:   $('#'+self.prefix+'_search_btn'),
        msg:   $('#'+self.prefix+'_search_msg'),
        spin:  $('#'+self.prefix+'_search_spin'),
        more_btn: $('#'+self.prefix+'_search_more_btn')
      }

      function dosearch(text_elem) { 
        return function() {
          window.scrollTo(0,1)

          app.model.page.prev('search')
          var rawterms = text_elem.val()
          self.query(rawterms) 
        }
      }

      self.elem.btn.bind(C.quicktap,dosearch(self.elem.text))
      self.elem.text.keypress(util.enterkey(dosearch(self.elem.text)))

      self.elem.results_btn = self.el.find('a.'+self.prefix+'_search_btn')
      self.elem.results_text = self.el.find('input.'+self.prefix+'_search_text')
      
      self.elem.results_btn.bind(C.quicktap,dosearch(self.elem.results_text))
      self.elem.results_text.keypress(util.enterkey(dosearch(self.elem.results_text)))
      if( !mode.touch ) {
        self.elem.results_text.bind('blur',dosearch(self.elem.results_text))
      }

      var resultlistview = Backbone.View.extend(_.extend({},views.articlelist))

      self.resultlist = new resultlistview({
        isSearch:true,
        listelem:'#'+self.prefix+'_search_articles',
        itemelem:'#'+self.prefix+'_search_articles_item',
        name:'search',
        model:app.model.search,
        maxcount:self.maxcount,
        imgcode:'phf',
        catmodel:self.options.catmodel ||util.die('6522f5'),
        articlecustom:self.options.articlecustom
      })

      app.model.search.bind('article-list-update',function(){
        var list = app.model.search.full_article_list
        if( 0 === list.length ) {
          util.show(self.elem.msg.text( text.nothingfound ))
        }
        else {
          util.show(self.elem.msg.text( list.length+text.results_found ))
        }

        var show_more = (self.pagecount*self.maxcount)<list.length-self.maxcount
        util.showhide(self.elem.more_btn,show_more)

        self.scrollup()
      })

      self.elem.more_btn.bind(C.quicktap,function(){
        self.pagecount++
        app.model.search.page(self.pagecount,self.maxcount)
        self.scrollup && self.scrollup()
      })
    },

    render_impl: function() {
      var self=this;
    },

    scrollup: function() {
      var self=this;

      if( 'web' == mode.name ) {
        window.scrollTo(0,0)
      }
    },

    query: function( rawterms ) {
      var self=this;

      self.pagecount = 0

      var terms = slang.trim(rawterms).toLowerCase()
      self.elem.text.val(rawterms)
      self.elem.results_text.val(rawterms)

      if( mode.touch ) {
        util.closekeyboard(self.elem.text,self.elem.results_text)
      }

      if( 1 < terms.length ) {

        var pagetype = app.model.page.get('type') 
        if( 'search' !== pagetype ) {
          app.model.page.set({type:'search'})
        }

        self.spinup()
        app.navigate('#!search/'+ encodeURIComponent( terms ))
        app.model.search.query( terms, function(list) {
          self.terms = terms
          self.list = list
          setTimeout(self.spindown,400)

        })
      }
    },


    spinup: function() {
      var self=this;
      util.show(self.elem.spin.css({display:'block',opacity:1}))

      if( self.spinner ) {
        self.spinner.spin( self.elem.spin[0] )
      }
      else {
        self.spinner = new Spinner(spin_opts).spin( self.elem.spin[0] )
      }
    },

    spindown: function() {
      var self=this;
      if( self.spinner ) {
        self.elem.spin.fadeOut(750,function(){
          self.spinner.stop()
          util.hide(self.elem.spin)
        })
      }
    }
  })





  views.MastHead = views.Basic.extend({
    init_impl: function() {
      _.bindAll(this,'render')      
      var self=this;

      self.elem = {
        tagline: $('#'+self.selprefix+'_tagline'),
        edition: $('#'+self.selprefix+'_edition'),
        logo: $('#'+self.selprefix+'_logo')
      }
    },

    render_impl: function() {
      var self=this;

      var today = new Date()
      var isEditionDay = business.iseditionday(today)

      var editioncode = app.model.edition.get('code')
      if( (!editioncode || 'daily'==editioncode) && !isEditionDay ) {
        util.hide(self.elem.edition)
        util.show(self.elem.tagline)
        self.elem.logo.attr('src','img/dbpostlogo_'+self.prefix+'.png')
      }
      else {
        var edd

        if( editioncode && 'daily'!==editioncode ) {
          edd = business.yyyymmdd(editioncode)
        }
        else {
          edd = business.editiondate(new Date())
        }

        util.hide(self.elem.tagline)
        util.show(self.elem.edition.text( edd.toString('d MMMM yyyy') ))
        self.elem.logo.attr('src','img/sbpostlogo_'+self.prefix+'.png')
      }
    }
  })



  views.StoryListHeader = views.Basic.extend({
    init_impl: function() {
      _.bindAll(this,'render_impl')      
      var self=this;

      self.elem = {
        title:     $('#'+self.selprefix+'_title'),
        home_btn:  $('#'+self.selprefix+'_home_btn'),
        daily_btn: $('#'+self.selprefix+'_daily_btn'),
        anon:      $('#'+self.selprefix+'_anon')
      }

      self.elem.home_btn.bind(C.tap,function(){
        app.view.frontpage.gocat('Home')
      })

      self.elem.daily_btn.bind(C.tap,function(){
        util.hide(self.elem.anon)
        app.model.edition.set({formatdate:''})
        app.model.edition.set({code:'daily'})
        app.view.frontpage.render()
      })

    },

    render_impl: function() {
      var self=this;
      var cat = app.model.frontpage.get('cat')

      if( 'Home' === cat ) {
        util.hide(self.elem.home_btn)
      }
      else {
        util.show(self.elem.home_btn)
      }

      var catname = app.cats[cat].name || cat
      self.elem.title.text(catname)

      var user = app.model.user.get('user')
      var edition = app.model.edition.get('code')

      if( user && user.anon && 'daily'!=edition ) {
        util.show(self.elem.anon)
      }

      return true
    }
  })



  views.social_links = function(prefix) {
    var services = ['linkedin','twitter','facebook']
    services.forEach(function(service){
      $('#'+prefix+'_'+service).bind(C.tap,function(){
        window.location.href='/api/user/oauth/'+service+'/login?'+Math.random()
      })
    })
  }

  views.pagetype = {

    register: views.Basic.extend({
      init_impl: function() {
        _.bindAll(this,'render_impl')
        var self=this;

        self.name = 'register'
        self.el = $('#register_view')

        self.elem = {
          email: $('#register_email'),
          name: $('#register_name'),
          password: $('#register_password'),
          repeat: $('#register_repeat'),
          msg: $('#register_msg')
        }

        self.elem.email.bind('blur',function(){ window.scrollTo(0,1) })
        self.elem.name.bind('blur',function(){ window.scrollTo(0,1) })
        self.elem.password.bind('blur',function(){ window.scrollTo(0,1) })
        self.elem.repeat.bind('blur',function(){ window.scrollTo(0,1) })

        views.social_links(self.name)

        $('#register_registerbtn').bind(C.tap,function(){
          if( mode.touch ) {
            self.elem.email.blur()
            self.elem.name.blur()
            self.elem.password.blur()
            self.elem.repeat.blur()
          }

          var data = {
            email:    self.elem.email.val(),
            name:     self.elem.name.val(),
            password: self.elem.password.val(),
            repeat:   self.elem.repeat.val()
          }
          data.nick = data.email
          
          if( data.password !== data.repeat ) {
            self.elem.msg.text( text.password_mismatch )
          }
          else if( '' === data.email || '' === data.name || '' === data.password ) {
            self.elem.msg.text( text.enter_all_fields )
          }
          else {
            app.model.user.register(data,function(err){

              if( err ) {
                self.elem.msg.text( text.already_registered )
              }
              else {
                app.model.page.set({message:'postregister'})
                app.model.user.load(function(){
                  self.options.success && self.options.success() 
                })
              }
            })
          }
        })
      },

      render_impl: function() {
        var self=this;
        self.elem.msg.text('')
      }
    }),


    login: views.Basic.extend({
      init_impl: function() {
        _.bindAll(this,'render_impl')
        var self=this;
        self.name = 'login'
        self.el = $('#login_view')

        self.elem = {
          email: $('#login_email'),
          password: $('#login_password'),
          msg: $('#login_msg'),
          btn: $('#login_loginbtn'),
          remind_btn: $('#login_reminderbtn')
        }

        views.social_links(self.name)

        function do_login(){
          if( mode.touch ) {
            util.closekeyboard(
              self.elem.email,
              self.elem.password
            )
          }

          var data = {
            email:    self.elem.email.val(),
            password: self.elem.password.val()
          }
          data.nick = data.email
          
          if( '' === data.email || '' === data.password ) {
            self.elem.msg.text( text.enter_all_fields )
          }
          else {
            app.model.user.login(data,function(err,res){
              if( err ) log('error',err);
              if( err || !res.ok ) {
                if( 'max-installs' === res.why ) {
                  self.elem.msg.html( text.maxinstalls )
                }
                else self.elem.msg.text( text.login_failed )
              }
              else {
                app.model.page.set({message:'postregister'})
                app.model.user.load(function(user){
                  log('user',user)
                  self.options.success && self.options.success() 
                })
              }
            })
          }
        }

        self.elem.btn.bind(C.tap,do_login)
        self.elem.password.keypress(util.enterkey(do_login))

        self.elem.remind_btn.bind(C.tap,function(){
          var email = self.elem.email.val()
          if( '' === email || -1 === email.indexOf('@') ) {
            self.elem.msg.text( text.invalidemail )
          }
          else {
            app.model.user.remind(email,function(err,res){
              self.elem.msg.text( (res && res.ok) ? text.remindersent : text.unknownemail )
            })
          }
        })
      },

      render_impl: function() {
        this.elem.msg.text('')
      }
    }),

    
    accdet: views.Basic.extend({
      init_impl: function() {
        _.bindAll(this,'render_impl','userload')
        var self=this;
        self.name = 'accdet'
        self.el = $('#accdet_view')

        self.elem = {
          logout_btn: $('#accdet_logoutbtn')
        }

        self.elem.logout_btn.bind(C.tap,function(){
          app.model.user.logout(function(){
            self.options.logout && self.options.logout() 
          })
        })

        self.elem = {
          email: $('#accdet_email'),
          name: $('#accdet_name'),
          password: $('#accdet_password'),
          repeat: $('#accdet_repeat'),
          msg: $('#accdet_msg'),
          form: $('#accdet_form'),
          social: $('#accdet_social'),
          social_icon: $('#accdet_social_icon'),
          social_nick: $('#accdet_social_nick'),
          passarea: $('#accdet_passarea')
        }

        self.elem.email.bind('blur',function(){ window.scrollTo(0,1) })
        self.elem.name.bind('blur',function(){ window.scrollTo(0,1) })
        self.elem.password.bind('blur',function(){ window.scrollTo(0,1) })
        self.elem.repeat.bind('blur',function(){ window.scrollTo(0,1) })


        $('#accdet_savebtn').bind(C.tap,function(){

          if( mode.touch ) {
            util.closekeyboard(
              self.elem.email,
              self.elem.name,
              self.elem.password,
              self.elem.repeat
            )
          }

          var data = {
            orig_email: app.model.user.get('user').email,
            email:      self.elem.email.val(),
            name:       self.elem.name.val(),
            password:   self.elem.password.val(),
            repeat:     self.elem.repeat.val()
          }
          data.nick = data.email
          
          if( data.password !== data.repeat ) {
            self.elem.msg.text( text.password_mismatch )
          }
          else if( '' === data.email || '' === data.name ) {
            self.elem.msg.text( text.enter_all_fields )
          }
          else {
            app.model.user.save(data,function(err){
              if( err ) {
                self.elem.msg.text( text.save_failed )
              }
              else {
                app.model.user.load()
                self.elem.msg.text( text.account_updated )
              }
            })
          }
        })
      },

      render_impl: function() {
        var self=this;
        this.elem.msg.text('')
        
        var user = app.model.user.get('user')

        if( user && user.social ) {
          this.elem.social.removeClass('hide')
          this.elem.form.addClass('hide')

          if( 'mob'==mode.name ) {
            this.elem.social_icon.attr('src','img/icon_'+user.social.service+'32.png')
          }
          else {
            this.elem.social_icon.attr('src','img/'+user.social.service+'-64.png')
          }

          this.elem.social_nick.text(user.nick)
        }
        else {
          this.elem.social.addClass('hide')
        }

        this.elem.form.removeClass('hide')

        if( user ) {
          var enteremail = true

          if( user.email && 0 !== user.email.indexOf('@@@')) {
            this.elem.email.val(user.email)
            enteremail = false
          }

          if( user.name ) {
            this.elem.name.val(user.name)
          }

          if( enteremail ) {
            self.elem.msg.text( text.enteremail )
          }
        }

        if( user.passlock ) {
          util.hide(self.elem.passarea)
        }
        else {
          if( app.model.page.get('password_reset') ) {
            self.elem.msg.text( text.reset_password )
            app.model.page.set({password_reset:false})
            return true
          }
        }
      },

      userload: function() {
        var self=this;
        self.dirty=true
      }
    }),


    editions: views.Basic.extend({
      init_impl: function() {
        _.bindAll(this,'render_impl','hash')
        var self=this;

        self.options.pagetype = self.options.pagetype || 'editions'

        self.prefix = self.options.prefix || self.prefix

        self.el = $('#'+self.prefix+'_editions')

        self.name = self.name || 'editions'

        self.elem = {
          btn:       $('a.'+self.prefix+'_editions_btn'),
          daily_btn: $('a.'+self.prefix+'_dailynews_btn')
        }


        self.editionslist = views.list(
          '#'+self.prefix+'_editions_list',
          '#'+self.prefix+'_editions_item',
          {
            'h4.displaydate':function(item,elem){
              var html = item.displaydate
              if( item.icon ) {
                html = '<img src="/img/icon_home.png" align="center">&nbsp;'+html
              }
              return html
            },
            'a.edition_buy_btn':function(item,elem){
              if( item.access ) elem.remove()
              else if( 'daily'!=item.code) {
                util.show(elem)
              }
            },
            'p.edition_purchased':function(item,elem){
              if( !item.access ) elem.remove()
              else util.show(elem)
            }
          },
          null,
          function(item,elem,i,list) {
            return function(event) {
              if( !item.access && 'daily'!=item.code) {
                store.set('jump',{type:'edition',code:item.code})
                var purchase = {pub:item.editiondate}
                store.set('purchase',purchase)
                app.model.page.set({purchase:purchase})
                app.model.page.set({type:'purchase'})
              }
              else {
                var editiondate = business.yyyymmdd(item.code)
                app.model.edition.set({formatdate:editiondate.toString('d MMMM yyyy')})
                app.model.edition.set({code:item.code})
                app.model.page.set({type:'front'})
                app.view.frontpage.trigger('frontpage-render')
                app.navigate('!edition/'+item.code)
              }
            }
          }
        )

        self.elem.btn.bind(C.tap,function(){
          app.model.user.load(function(){
            app.model.page.set({type:'editions'})        
          })
        })

        self.elem.daily_btn.bind(C.tap,function(){
          // FIX: method on frontpage?
          app.model.edition.set({code:'daily'})
          app.model.frontpage.set({cat:'Home',subcat:''})
          app.model.page.set({type:'front'})
          app.view.frontpage.trigger('frontpage-render')
          app.navigate('')
        })


        self.selectlist = views.list(
          '#'+self.prefix+'_editions_select_list',
          '#'+self.prefix+'_editions_select_item',
          {
            '.year':'year',
            '.divider':function(item,elem,i,list) {
              if( i === list.length-1 ) {
                elem.empty()
              }
            }
          },
          null,
          function(item) {
            return function() {
              app.model.page.set({editions_select:item.year})
              self.show(true)
            }
          }
        )

      },

      render_impl: function() {
        var self=this;

        var access = app.model.user.access()

        var select = app.model.page.get('editions_select') || 'latest'

        var editions = []
        if( 'latest' === select ) {
          editions.push({displaydate:'Daily News',code:'daily',icon:'icon_home.png'})
        }

        var d = new Date()
        if( 'latest' !== select ) {
          d = new Date(parseInt(select,10),11,31)
        }

        var ed = business.editiondate(d)

        var ed_ymd = business.yyyymmdd(ed)
        if( app.conf.nonsunday[ ''+ed_ymd ] ) {
          ed = business.yyyymmdd( parseInt( app.conf.nonsunday[ ''+ed_ymd ][0], 10 ) )
        }

        var t = ed.getTime()

        for( var i = C.editionstart; i < C.numeditions; i++ ) {
          var edition = {}

          var et = t-(i*1000*business.WEEK)
          var dd = new Date(et)
          var edd = business.editiondate(dd)
          var edc = business.yyyymmdd(edd)

          edition.editiondate = edd
          edition.displaydate = edd.toString('d MMMM yyyy')
          edition.code = edc
          edition.access = access.access(edc)

          editions.push(edition)
        }

        self.editionslist.render(editions)

        if( !navigator.device ) {
          self.selectlist.render([
            {year:'latest'},
            {year:'2010'},
            {year:'2009'},
            {year:'2008'},
            {year:'2007'},
            {year:'2006'},
            {year:'2005'},
            {year:'2004'}
          ])
          util.show(self.selectlist.elem)
        }

        return true
      },

      hash: function() {
        var self=this;
        return 'editions/latest'
      }
    }),


    purchase: views.Basic.extend({
      init_impl: function() {
        _.bindAll(this,'render_impl')
        var self=this;

        self.name = self.name || 'purchase'

        self.options.hash     = self.options.hash     || self.name
        self.options.pagetype = self.options.pagetype || self.name
        self.selprefix = self.prefix+'_'+self.name

        self.prefix = self.options.prefix || self.prefix
        self.el = $('#'+self.prefix+'_'+self.name)

        self.elem = {
          btn:  $('a.'+self.selprefix+'_btn'),
          edition_date: self.el.find('span.edition_date'),
          today_date: self.el.find('span.today_date'),
          
          single:  $('#'+self.selprefix+'_single'),
          monthly:   $('#'+self.selprefix+'_monthly'),
          quarterly: $('#'+self.selprefix+'_quarterly'),
          annual:  $('#'+self.selprefix+'_annual'),

          launch: $('#'+self.selprefix+'_launch'),
          desc: $('#'+self.selprefix+'_desc'),
          proceed: $('#'+self.selprefix+'_proceed'),
          email: $('#'+self.selprefix+'_email'),
          msg: $('#'+self.selprefix+'_msg'),

          status_msg: $('#'+self.selprefix+'_status_msg')
        }


        function highlight(kind) {
          for( var k in {single:1,monthly:1,quarterly:1,annual:1}) {
            if( k === kind ) {
              self.elem[k].addClass('high')
            }
            else {
              self.elem[k].removeClass('high')
            }
          }
        }
        

        function do_prelaunch() {
          self.elem.launch.slideDown()
          self.elem.desc.text( self.purchase.desc )
        }


        function launch_purchase() {
          var spec = {
            edition: self.purchase.edition,
            sid: self.purchase.sid,
            kind: self.purchase.kind,
            email: self.purchase.email
          }
          log('spec',spec)

          if( 'single' === spec.kind ) {
            spec.code = 'ie.thepost.i'+mode.name+'.sed1.'+spec.edition

            app.submanager.buy(spec) 
          }
          else {
            spec.code = 'ie.thepost.i'+mode.name+'.sub1.'+spec.kind+'1'

            var user = app.model.user.get('user')
            if( !mode.device && (!user || !user.regcard) ) {
              app.submanager.regcard(spec) 
            }
            else {
              app.submanager.subscribe(spec) 
            }
          }
        }


        function do_purchase(kind,duration) {
          return function() {
            highlight(kind)

            self.purchase.kind = kind
            self.purchase.desc = 
              self.elem[kind].find('h4').text()+': '+ 
              self.elem[kind].find('p.when').text() 

            var auth = app.model.user.get('auth')
            var user = app.model.user.get('user')

            if( !mode.device && !auth  ) {
              do_prelaunch()
            }
            else if( !mode.device && auth && !user.email) {
              do_prelaunch()
            }
            else {
              if( user ) {
                self.purchase.email = user.email
              }
              launch_purchase()
            }
          }
        }



        function do_proceed() {
          var email = self.elem.email.val()
          if( !util.validemail( email ) ) {
            return self.elem.msg.text(text.invalidemail)          
          }

          app.model.user.checkemail(email,function(err,res){
            if( res.registered ) {
              if( 'web' == mode.name ) {
                app.model.page.set({type:'login'})
                app.view.frontpage.trigger('frontpage-render')
              }
              else if( 'pad' == mode.name ) {
                app.view.loginview.show()
              }
              else if( 'mob' == mode.name ) {
                app.model.tabbar.set({tab:'login'}) 
              }
            }
            else {
              self.purchase.email = email
              launch_purchase()
            }
          })
        }


        self.elem.single.bind(C.tap,do_purchase(  'single'))
        self.elem.monthly.bind(C.tap,do_purchase(   'monthly'))
        self.elem.quarterly.bind(C.tap,do_purchase( 'quarterly'))
        self.elem.annual.bind(C.tap,do_purchase(  'annual'))

        self.elem.proceed.bind(C.tap,do_proceed)
        self.elem.email.keypress(util.enterkey(do_proceed))
      },

      render_impl: function() {
        var self=this;

        var purchase = app.model.page.get('purchase')
        if( !purchase ) {
          purchase = store.get('purchase')
          if( !purchase ) {
            purchase = {pub:new Date()}
          }
          else {
            purchase.pub = app.model.articlestore.parseDate(purchase.pub)
          }
        }
        self.purchase = purchase
        log('purchase',purchase)

        var ed = business.editiondate(purchase.pub)
        self.purchase.edition = business.yyyymmdd(ed)

        var today = new Date()

        self.elem.edition_date.text( ed.toString('d MMM yyyy') )
        self.elem.today_date.text( today.toString('d MMM yyyy') )

        var purchase_status = app.model.page.get('purchase_status')
        var purchase_code = app.model.page.get('purchase_code')
        views.purchase_handlemsgs(purchase_status,purchase_code,self.elem.status_msg)
        app.model.page.set({purchase_status:null})
      },


      scrollup: function() {
        if( 'web' === mode.name ) {
          window.scrollTo(0,0)
        }
        else if( 'pad' === mode.name ) {
          app.view.frontpage.scrollup()
        }
      }
    })
  }


  views.purchase_handlemsgs = function(purchase_status,purchase_code,status_msg_elem) {
    log('purchase_handlemsgs',purchase_status,purchase_code)

    if( 'cancelled' === purchase_status ) {
      var msgtext = text.purchase_cancelled
      
      if( 'E02'===purchase_code ) {
        msgtext = text.purchase_card_used
      }
      
      status_msg_elem.text(msgtext)
      util.show(status_msg_elem)
      
    }
    else {
      util.hide(status_msg_elem)
    }
  }



  views.Slider = Backbone.View.extend({
    initialize: function() {
      _.bindAll(this,'render')
      var self=this;
      
      self.name  = self.options.name
      self.model = self.options.model

      self.el = $('#'+mode.name+'_slider_'+self.name)

      self.elem = {knob:self.el.find('.knob')}

      self.knobsize = self.elem.knob.width()
      self.max = self.el.width()-self.knobsize

      setTimeout( function() {
        self.knobsize = self.elem.knob.width()
        self.max = self.el.width()-self.knobsize
      }, 1000 )
      
      var touchy = mode.touch
      var move = touchy ? 'touchmove' : 'mousemove'
      Zepto('#'+mode.name+'_slider_'+self.name).bind(move,function(event){
        var pageX = touchy ? event.touches[0].pageX : event.pageX;
        var offset = pageX-20-22
        //$('#__val__').text(offset)

        if( self.options.adjust ) {
          offset += self.options.adjust()
        }

        if( offset < 0 ) {
          offset = 0
        }
        else if( self.max < offset ) {
          offset = self.max
        }

        Firmin.translateX( self.elem.knob[0], offset )      
        var newval = Math.floor( ((offset+11) / self.max ) * 10 )

        var val = self.model.get(self.name)
        if( newval !== val ) {
          var set = {}; set[self.name] = newval; set['old_'+self.name] = val
          self.model.set(set)
        }
      })
    },

    render: function() {
      var self=this;
      
      var val = self.model.get(self.name)
      var offset = val * Math.floor( self.max / 10 )

      util.do_firmin('slider render',self.elem.knob[0],function(){
        Firmin.translateX( self.elem.knob[0], offset )   
      })
    }
  })



  views.OverviewColumn = Backbone.View.extend({
    name: 'Overview',

    el: $('#front_thirdcol'),

    initialize: function() {
      _.bindAll(this,'render','showmpu')
      var self=this;

      self.catarts = $('#front_overview_catarts')

      self.item_tm = $('#front_overview_cat_tm').clone()
      self.art_tm = $('#front_overview_art_tm').clone()

      self.mpu = $('#front_thirdcol_mpu')

      self.done = {}
    },

    render: function() {
      var self=this;

      self.showmpu(0)

      function renderboxes(boxes) {
        for( var i = 0; i < boxes.length; i++ ) {
          var box = boxes[i]

          var item = self.item_tm.clone()
          if( 0 === i ) {
            item.addClass('top')
          }

          item.find('h2').text(box.c)

          var arts = box.a
          var arts_div = item.find('div.front_overview_arts')

          // prev,next buttons in ipad
          var ssmap
          if( 'pad' === mode.name ) {
            ssmap = {showstory:{}}
          }

          for( var j = 0; j < arts.length; j++ ) {
            var art = arts[j]
            var div = self.art_tm.clone().removeClass('hide')

            var markpremium = true // !('Home'==cat&&(''==subcat||'News'==subcat))

            if( markpremium && 'newspaper' === art.ty ) {
		art.h = views.markpremium(art.h,'small')
            }

            div.find('p').html(art.h)

            if( 'Comment' == box.c ) {
              div.find('h3').removeClass('hide').text(art.sc)
            }

            arts_div.append(div);

            var aiv = new views.ArticleInfoView({
              el:div,
              sid:art.sid,
              pub:art.pub,
              type:art.ty,
              list:arts,
              index:j,
              listview:ssmap,
              whence:'overview'
            })

            if( 'pad' === mode.name ) {
              ssmap.showstory[art.sid] = aiv
            }
          }

          item.removeClass('hide')

          self.el.append(item)
        }
      }

      if( !self.done.catarts ) {
        self.catarts.empty()
        self.done.catarts = true

        var boxes = app.model.overview.get('overview')
        if( boxes ) {
          renderboxes(boxes)
        }
        else {
          app.model.overview.load( renderboxes )
        }
      }
    },

    showmpu: function( cols ) {
      var self=this;
      var pagetype = app.model.page.get('type')
      
      if( 'article' == pagetype && 2 == cols ) {
        self.mpu.removeClass('hide')
      }
      else {
        self.mpu.addClass('hide')
      }
    }

  })

}

