var PixelsPerInch = 4;
var InchesPerFoot = 12;
var PixelsPerFoot = PixelsPerInch * InchesPerFoot;
var StartCeilingHeightFt = 9;
var StartHoodWidthIn = 66;
var CounterHeightIn = 37.5;
var CabinetHeight = 167;
var CrownHeight = 3.5;
var BuilderWidth = 500;
var ExtensionHeight = 12;

VillaStone.HoodBuilder = Class.create({
    hoodStyle: 'angled', 
    canopyStyle: 'radius',
    
    style: 'angled', // angled | radius | arched
    alt: false,
    heightSlider: false,
    widthSlider: false,

    hoodBuilder: false,
    
    frontView: false,
    extension: false,
    crown: false,
    hood: false,
    counter: false,
    rangetop: false,
    canopy: false,
    parts: false,
    attachmentList: false,
    
    sideView: false,
    sideExtension: false,
    sideCrown: false,
    sideHood: false,
    sideCanopy: false,
    sideInlayDesign: false,
    sideCounter: false,
    sideCorbel: false,
    
    inlaySelect: false,
    inlayDesign: false,
    photoLink: false,
    corbelSelect: false,
    corbelLeft: false,
    corbelRight: false,
    corbelPhotoLink: false,
    light: false,
    leftCabinet: false,
    rightCabinet: false,
    hoodStyles: {
        'angled' : {
            minCeilingHeight: 8,
            heights: {'8': 18, '9': 26.50, '10': 38, '11':38, '12':38}
        },
        'arched' : {
            minCeilingHeight: 9,
            heights: {'9': 23.25, '10': 35, '11':35, '12':35}
        }
    },
    canopyStyles: {
        'inlay' : {
            minSystemWidth: 42,
            maxSystemWidth: 90,
            height: { inches: 10.25, pixels: 43 }
        },
        'radius' : {
            minSystemWidth: 54,
            maxSystemWidth: 78,
            height: { inches: 15, pixels: 61 }
        }
    },
    hoodHeightsPrecise: {8:17.75, 9:26.625, 10:38.625, 11:38.625, 12:38.625},
    corbelInfo: { 
        'CB05x37SM': { name: 'Saint Michelle - 5&rdquo;w x 24&rdquo;h x 24&rdquo;d',  width: 5.5,  height: 35,    depth: 22,    gallery: [] }, 
        'CB05X12CH': { name: 'Chablis - 5&rdquo;w x 12&rdquo;h x 12&rdquo;d',         width: 5,    height: 12,    depth: 12,    gallery: [] }, 
        'CB06X10AC': { name: 'Acanthis - 6.5&rdquo;w x 10.5&rdquo;h x 7&rdquo;d',     width: 6.5,  height: 10.5,  depth: 7,     gallery: [] }, 
        'CB05X24SE': { name: 'Seville - 5.5&rdquo;w x 24&rdquo;h x 15&rdquo;d',       width: 5.5,  height: 24,    depth: 15,    gallery: ['01.jpg','05.jpg','11.jpg'] }, 
        'CB07X25BR': { name: 'Brittany - 7.5&rdquo;w x 25&rdquo;h x 9.75&rdquo;d',    width: 7.5,  height: 25,    depth: 9.75,  gallery: ['06.jpg','10.jpg'] },
        'CB07X40NO': { name: 'Normandy - 7.5&rdquo;w x 40&rdquo;h x 11&rdquo;d',      width: 7.5,  height: 40,    depth: 11,    gallery: [] }, 
        'CB06X40LO': { name: 'Lorraine - 6&rdquo;w x 40&rdquo;h x 20&rdquo;d',        width: 6,    height: 40,    depth: 20,    gallery: ['02.jpg'] }
    },
    inlayInfo: {
        'flatstock':            { part: 'ILFS',     name: 'Flat Stock Inlay',                           gallery: [] },
        'arabesque':            { part: 'ILAR',     name: 'Arabesque Inlay',                            gallery: [] },                  
        'grape':                { part: 'ILGV',     name: 'Grape Vine Inlay',                           gallery: ['01.jpg', '11.jpg'] },
        'floral':               { part: 'ILFL',     name: 'Floral Inlay',                               gallery: ['06.jpg', '10.jpg'] },
        'floral_shell':         { part: 'ILSK-FL',  name: 'Shell Keystone - Floral Inlay',              gallery: ['03.jpg', '04.jpg', '08.jpg', '09.jpg' ] },
        'fleurdelis':           { part: 'ILFK-FS',  name: 'Fleur-de-lis Keystone - Flat Stock Inlay',   gallery: ['05.jpg'] },
        'arabesque_keystone':   { part: 'ILFK-AR',  name: 'Fleur-de-lis Keystone - Arabesque Inlay',    gallery: ['07.jpg'] }
    },
    attachments: {
        'KHVIEN0842':               { files: ['/Files/HoodSpecs/Villa Stone Designs - Hood Specs - KHVIEN0842.pdf'] },
        'KHVIEN0848':               { files: ['/Files/HoodSpecs/Villa Stone Designs - Hood Specs - KHVIEN0848.pdf'] },
        'KHVIEN0948':               { files: ['/Files/HoodSpecs/Villa Stone Designs - Hood Specs - KHVIEN0948.pdf'] },
        'KHVIEN0954':               { files: ['/Files/HoodSpecs/Villa Stone Designs - Hood Specs - KHVIEN0954.pdf'] },
        'KHVIEN0960':               { files: ['/Files/HoodSpecs/Villa Stone Designs - Hood Specs - KHVIEN0960.pdf'] },
        'KHVIEN0966':               { files: ['/Files/HoodSpecs/Villa Stone Designs - Hood Specs - KHVIEN0966.pdf'] },
        'KHVIEN0972':               { files: ['/Files/HoodSpecs/Villa Stone Designs - Hood Specs - KHVIEN0972.pdf'] },
        'KHVIEN0990':               { files: ['/Files/HoodSpecs/Villa Stone Designs - Hood Specs - KHVIEN0990.pdf'] },
        'KHVIEN1048':               { files: ['/Files/HoodSpecs/Villa Stone Designs - Hood Specs - KHVIEN1048.pdf'] },
        'KHVIEN1054':               { files: ['/Files/HoodSpecs/Villa Stone Designs - Hood Specs - KHVIEN1054.pdf'] },
        'KHVIEN1060':               { files: ['/Files/HoodSpecs/Villa Stone Designs - Hood Specs - KHVIEN1060.pdf'] },
        'KHVIEN1066':               { files: ['/Files/HoodSpecs/Villa Stone Designs - Hood Specs - KHVIEN1066.pdf'] },
        'KHVIEN1072':               { files: ['/Files/HoodSpecs/Villa Stone Designs - Hood Specs - KHVIEN1072.pdf'] },
        'KHVIEN1090':               { files: ['/Files/HoodSpecs/Villa Stone Designs - Hood Specs - KHVIEN1090.pdf'] }
    },
    width: StartHoodWidthIn,
    height: StartCeilingHeightFt,
    
    showCrown: false,
    corbel: false,
    extensionPart: false,
    inlayPart: false,
    
    measurements: false,
    sideMeasurements: false,
    
    rulerCorbelSpacing: false,
    rulerInlayWidth: false,
    rulerInlayBottom: false,
    rulerTopWidth: false,
    rulerInlayHeight: false,
    rulerSystemHeight: false,
    rulerFloorHeight: false,
    rulerHoodHeight: false,
    rulerStoveWidth: false,
    rulerSideTop: false,
    rulerSideBottom: false,
    rulerSideInlayBottom: false,
    
    blowerType: false,
    blowerBrand: false,
    blowerDuctSize: false,
    blowerPower: false,
    
    dropdownDuctSize: false,
    dropdownPower: false,
    
    clearCorbelLink: false,
    
    initialize: function() {
        this.hoodBuilder = $('hoodBuilder');
        
        this.sideView = $('sideView');
        
        // Front View
        this.frontView = $('frontView');
        var top = this.frontView.down('div.builderTop');
        this.extension = top.down('div.extension');
        this.crown = top.down('div.crown');
        this.hood = top.down('div.hood');
        this.canopy = top.down('div.canopy');
        this.inlayDesign = this.canopy.down('div.design');
        this.light = this.canopy.down('div.light');
        this.corbelLeft = this.canopy.down('.corbelLeft');
        this.corbelRight = this.canopy.down('.corbelRight');
        this.leftCabinet = top.down('.leftcabinet');
        this.rightCabinet = top.down('.rightcabinet');
        this.counter = this.frontView.down('div.counter');
        this.rangetop = this.counter.down('div.rangetop');
        
        // Side View
        this.sideExtension = this.sideView.down('div.extension');
        this.sideCrown = this.sideView.down('div.crown');
        this.sideHood = this.sideView.down('div.hood');
        this.sideCanopy = this.sideView.down('div.canopy');
        this.sideInlayDesign = this.sideCanopy.down('div.design');
        this.sideCorbel = this.sideCanopy.down('div.corbel');
        this.sideCounter = this.sideView.down('div.counter');
        
        // Controls
        this.attachmentList = $('attachmentList');
        this.parts = $('parts');
        this.inlaySelect = $('inlay_select');
        this.corbelSelect = $('corbel_select');
        this.photoLink = $('photoLink');
        this.corbelPhotoLink = $('corbelPhotoLink');
        
        // Rulers
        this.measurements = $('measurements');
        this.sideMeasurements = $('sideMeasurements');
        
        this.rulerCorbelSpacing = $('rulerCorbelSpacing');
        this.rulerInlayWidth = $('rulerInlayWidth');
        this.rulerInlayBottom = $('rulerInlayBottom');
        this.rulerTopWidth = $('rulerTopWidth');
        this.rulerInlayHeight = $('rulerInlayHeight');
        this.rulerSystemHeight = $('rulerSystemHeight');
        this.rulerFloorHeight = $('rulerFloorHeight');
        this.rulerHoodHeight = $('rulerHoodHeight');
        this.rulerStoveWidth = $('rulerStoveWidth');
        this.rulerSideTop = $('rulerSideTop');
        this.rulerSideBottom = $('rulerSideBottom');
        this.rulerSideInlayBottom = $('rulerSideInlayBottom');
        
        var styleLinks = $$('#style_select div.style a');
        for (var i=0; i<styleLinks.length; i++) {
            styleLinks[i].observe('click', function(e) { this.selectSystemStyle(e.element()); e.stop(); }.bind(this));
        }
        this.selectSystemStyle($('style_select').down('div.sel a'));
        
        this.widthSlider = new Control.Slider('handleHoodWidth','sliderHoodWidth', { 
            sliderValue: 66,
            minimum: 42,
            maximum: 90,
            values: [42, 48, 54, 60, 66, 72, 78, 84, 90],
            range: $R(41.5,90.6),
            onSlide: function(widthInInches){
                if (widthInInches != this.width) {
                    this.setHoodWidth(widthInInches, true);
                }
            }.bind(this),
            onChange: function(widthInInches){
                if (widthInInches != this.width) {
                    this.setHoodWidth(widthInInches, true);
                }
            }.bind(this)
        });
        
        this.heightSlider = new Control.Slider('handleCeilingHeight','sliderCeilingHeight', { 
            sliderValue: 9,
            minimum: 8,
            maximum: 12,
            values: [8, 9, 10, 11, 12],
            range: $R(7.95,12.05),
            onSlide: function(heightInFt){
                if (heightInFt != this.height) {
                    this.setCeilingHeight(heightInFt, true);
                }
            }.bind(this),
            onChange: function(heightInFt){
                if (heightInFt != this.height) {
                    this.setCeilingHeight(heightInFt, true);
                }
            }.bind(this)
        });
        
        var inlayChoices = this.inlaySelect.select('.inlay a');
        for (var i = 0; i<inlayChoices.length; i++) {
            inlayChoices[i].observe('click', function(e) {
                e.stop()
                this.selectInlay(e.element());
            }.bind(this));
        }
        this.selectInlay($('defaultInlay'));
        
        var corbelChoices = this.corbelSelect.select('.corbel a');
        for (var i = 0; i<corbelChoices.length; i++) {
            corbelChoices[i].observe('click', function(e) {
                e.stop()
                this.selectCorbel(e.element());
            }.bind(this));
        }
        this.clearCorbelLink = $('clearCorbel');
        this.clearCorbelLink.observe('click', function(e) { e.stop(); this.selectCorbel(null); }.bind(this));

        this.selectCorbel($('defaultCorbel'));
        
        // Bind 'Crown Moulding' checkbox events
        var crownCheck = $('checkCrownMoulding');
        crownCheck.checked = true;
        crownCheck.observe('click', function(e) {
            this.toggleCrownMoulding(e.element());
        }.bind(this));
        this.toggleCrownMoulding(crownCheck);
        
        // Bind 'Show Measurements' checkbox events
        var linkMeasurements = $('linkShowMeasurements');
        linkMeasurements.observe('click', function(e) {
            this.toggleMeasurements(e.element());
        }.bind(this));
        
        // Bind blower selection dropdowns
        this.dropdownDuctSize = $('dropdownDuctSize');
        this.dropdownPower = $('dropdownPower');
        this.blowerType = $('blowerType');
        this.blowerBrand = $('blowerBrand');
        this.blowerDuctSize = $('blowerDuctSize');
        this.blowerPower = $('blowerPower');
        var dropdowns = [this.blowerType, this.blowerBrand, this.blowerDuctSize, this.blowerPower];
        for (var i=0; i<dropdowns.length; i++) {
            var dropdown = dropdowns[i];
            dropdown.selectedIndex = 0;
            dropdown.disabled = false;
            dropdown.observe('change', this.selectBlower.bind(this));
            dropdown.observe('keyup', this.selectBlower.bind(this, dropdown));
        }
        this.selectBlower();
        
        this.refresh(false);
        
        var imagesToLoad = []
        for (var h=8; h<=10; h++) {
            for (var w=42; w<=90; w+=6) {
                imagesToLoad.push("/images/hood/hood_" + h + "ft_" + w + ".jpg");
            }
        }
        preloadImages(imagesToLoad);
    },
    
    selectSystemStyle: function(link) {
        if (link.tagName.toLowerCase() != 'a')
            link = link.up('a');
    
        link.up('div.selectStyle').select('.sel').each(function(item) { item.removeClassName('sel'); });
        link.up().addClassName('sel');
        
        var styleName = link.rel;
    
        if (styleName == 'arched') {
            this.selectHoodStyle('arched');
            this.selectCanopyStyle('radius');
        } else if (styleName == 'radius') {
            this.selectHoodStyle('angled');
            this.selectCanopyStyle('radius');
        } else if (styleName == 'inlay') {
            this.selectHoodStyle('angled');
            this.selectCanopyStyle('inlay');
        }
    },
    
    selectHoodStyle: function(styleName) {
        this.hoodBuilder.removeClassName(this.hoodStyle + '_hood');
        this.hoodStyle = styleName;
        this.hoodBuilder.addClassName(this.hoodStyle + '_hood');
        
        this.setCeilingHeight(this.height, false);
        this.setHoodWidth(this.width, false);
    },
    
    selectCanopyStyle: function(styleName) {
        this.hoodBuilder.removeClassName(this.canopyStyle + '_canopy');
        this.canopyStyle = styleName;
        this.hoodBuilder.addClassName(this.canopyStyle + '_canopy');
        
        // Show or hide the inlay selector
        if (this.canopyStyle == 'inlay' && !this.inlaySelect.visible()) {
            Effect.BlindDown(this.inlaySelect, { duration: 0.5 });
        } else if (this.canopyStyle != 'inlay' && this.inlaySelect.visible()) {
            Effect.BlindUp(this.inlaySelect, { duration: 0.5 });
        }
        
        var canopyFrontImage = '';
        var canopySideImage = '';
        if (this.canopyStyle == 'inlay') {
            canopyFrontImage = 'url(/images/inlays/base_mid.jpg)';
            canopySideImage = 'url(/images/inlays/base_mid.jpg)';
        } else if (this.canopyStyle == 'radius') {
            canopyFrontImage = 'url(/images/inlays/radius_canopy_' + this.width + '.jpg)';
            canopySideImage = 'url(/images/inlays/radius_canopy_side.jpg)';
        }
        
        var canopyHeightPx = this.canopyStyles[this.canopyStyle].height.pixels;
        
        this.canopy.setStyle({ backgroundImage: canopyFrontImage }); 
        this.sideCanopy.setStyle({ backgroundImage: canopySideImage }); 
        
        new Effect.Morph(this.canopy, { style: 'height: ' + canopyHeightPx + 'px', duration: 0.5 });
        new Effect.Morph(this.corbelLeft, { style: 'top: ' + canopyHeightPx + 'px', duration: 0.5 });
        new Effect.Morph(this.corbelRight, { style: 'top: ' + canopyHeightPx + 'px', duration: 0.5 });
        new Effect.Morph(this.sideCanopy, { style: 'height: ' + canopyHeightPx + 'px', duration: 0.5 });
        new Effect.Morph(this.sideCorbel, { style: 'top: ' + canopyHeightPx + 'px', duration: 0.5 });
        
        this.setCeilingHeight(this.height, false);
        this.setHoodWidth(this.width, false);
    },
    
    refresh: function(remeasure) {
        this.refreshPartsList();
        if (remeasure) this.refreshMeasurements();    
    },
    
    setCeilingHeight: function(heightInFt, adjustWidth) {
        var hoodStyle = this.hoodStyles[this.hoodStyle];
        if (hoodStyle.minCeilingHeight && hoodStyle.minCeilingHeight > heightInFt) {
            heightInFt = hoodStyle.minCeilingHeight;
            this.heightSlider.setValue(heightInFt);
        }
        
        var expanding = this.height < heightInFt;
        this.height = heightInFt;
        
        if (heightInFt == 10 && this.widthSlider.value == 42 && adjustWidth) {
            this.widthSlider.setValue(48);
        }
        
        var wallHeight = PixelsPerFoot * heightInFt;
        var counterHeight = CounterHeightIn * PixelsPerInch;
        var counterOffset = wallHeight - counterHeight + 5;
        var hoodHeight = (this.hoodStyles[this.hoodStyle].heights[heightInFt] * PixelsPerInch);
        var cabinetOffset = (wallHeight - counterHeight - CabinetHeight)/2 - 0;
        
        new Effect.Morph(this.counter, { style: 'height: ' + counterHeight + 'px; top: ' + counterOffset + 'px', duration: 0.5 });
        new Effect.Morph(this.sideCounter, { style: 'top: ' + (counterOffset) + 'px', duration: 0.5 });
        new Effect.Morph(this.sideView, { style: 'height: ' + wallHeight + 'px;', duration: 0.5 });
        
        this.adjustExtension();
        
        new Effect.Morph(this.frontView, { style: 'height: ' + wallHeight + 'px;', duration: 0.5 });
        new Effect.Morph(this.leftCabinet, { style: 'top: ' + cabinetOffset + 'px', duration: 0.5 });
        new Effect.Morph(this.rightCabinet, { style: 'top: ' + cabinetOffset + 'px', duration: 0.5 });
        
        // Adjust hood side view height and background image
        this.sideHood.setStyle({
            //backgroundImage: 'url(/images/hood/hood_side_' + Math.min(heightInFt, 10) + 'ft.jpg)' 
        });
        new Effect.Morph(this.sideHood, { style: 'height: ' + hoodHeight + 'px;', duration: 0.5 });
        
        // Adjust front view hood height
        new Effect.Morph(this.hood, {
            style: 'height: ' + hoodHeight + 'px;',
            duration: 0.5,
            afterFinish: function() {
                this.setHoodWidth(this.width, false);
                //window.setTimeout(function() { this.setHoodWidth(this.width, false); }.bind(this), 1);
            }.bind(this)
        });
        
        if (expanding && adjustWidth) {
            this.setHoodWidth(this.width, false);
        }
    },
    
    adjustOvenWidth: function() {
        var widthInInches = this.width;
        var corbelWarning = false;
        
        var ovenWidth = 36;
        if (this.width > 54) ovenWidth = 48;
        if (this.width > 66) ovenWidth = 60;
        
        var corbelWidths = this.getCorbelWidths();
        if (corbelWidths && (corbelWidths.between-2) < ovenWidth) {
            if (ovenWidth > 36) {
                ovenWidth -= 12;
            } else {
                corbelWarning = true;
            }
        }
        
        this.counter.setStyle({ backgroundImage: 'url(/images/counters/counter_' + ovenWidth + '.jpg)' });
        this.rangetop.setStyle({ backgroundImage: 'url(/images/counters/rangetop_' + ovenWidth + '.jpg)' });
        this.light.setStyle({ backgroundImage: 'url(/images/light_' + ovenWidth + '.jpg)' });
        
        if (corbelWarning) {
        }
        
        return { ovenWidth: ovenWidth, corbelWarning: corbelWarning };
    },
    
    setHoodWidth: function(widthInInches, adjustHeight) {
        // First constrain width to hood style limitations
        var canopyStyle = this.canopyStyles[this.canopyStyle];
        if (canopyStyle.minSystemWidth && canopyStyle.minSystemWidth > widthInInches) {
            widthInInches = canopyStyle.minSystemWidth;
            this.widthSlider.setValue(widthInInches);
        } else if (canopyStyle.maxSystemWidth && canopyStyle.maxSystemWidth < widthInInches) {
            widthInInches = canopyStyle.maxSystemWidth;
            this.widthSlider.setValue(widthInInches);
        }
        
        // Special case for angled style - don't allow 42" width on 10ft model (too thin at the top)
        if (this.canopyStyle == 'inlay' && this.height >= 10 && widthInInches == 42 && this.widthSlider.value == 42) {
            widthInInches = 48;
            this.widthSlider.setValue(widthInInches);
        } 
        
        this.width = widthInInches;
        var hoodHeight = Math.min(this.height, 10);
        var bottomWidth = widthInInches * PixelsPerInch;
        
        var hoodBg = 'url(/images/hood/hood_' + hoodHeight + 'ft_' + this.width +'.jpg)';
        if (this.hoodStyle == 'arched') {
            hoodBg = 'url(/images/hood/arched_' + this.width + '.jpg)';
        }
        
        var canopyBg = '';
        if (this.canopyStyle == 'inlay') {
            canopyBg = 'url(/images/inlays/base_mid.jpg)';
        } else if (this.canopyStyle == 'radius') {
            canopyBg = 'url(/images/inlays/radius_canopy_' + this.width + '.jpg)';
        }
        
        var cabinetWidth = 150 - (widthInInches-42)/6*12;
        
        this.leftCabinet.setStyle({width: cabinetWidth + 'px'});
        this.rightCabinet.setStyle({width: cabinetWidth + 'px'});
        
        this.hood.setStyle({ width: bottomWidth + 'px', backgroundImage: hoodBg });
        
        var sideHoodBg = 'url(/images/hood/hood_side_' + hoodHeight + 'ft.jpg)';
        if (this.hoodStyle == 'arched') {
            sideHoodBg = 'url(/images/hood/arched_side.jpg)';
        }
            
        this.sideHood.setStyle({ backgroundImage: sideHoodBg });
        this.canopy.setStyle({width: bottomWidth + 'px', backgroundImage: canopyBg });
        
        var crownOffset = this.height == 8 ? 50 : 76;
        var crownWidth = bottomWidth - crownOffset;
        this.crown.setStyle({width: crownWidth + 'px'});
        this.sideCrown.setStyle({ marginLeft: (this.height == 8 ? 78 : this.hoodStyle == 'arched' ? 91 : 97) + 'px' });
        this.sideExtension.setStyle({ marginLeft: (this.hoodStyle == 'arched' ? 98 : 103) + 'px' });
        
        var extensionWidth = bottomWidth - 90;
        this.extension.setStyle({width: extensionWidth + 'px'});
        this.adjustExtension();
        
        this.adjustOvenWidth();
        this.selectBlower();
        this.refresh(true);
    },
    
    adjustExtension: function() {
        if (this.height > 10 && this.width > 48) {
            var numExtensions = this.height - 10;
            var extensionHeight = numExtensions * PixelsPerFoot;
            
            new Effect.Morph(this.extension, { style: 'height:' + extensionHeight + 'px', duration: 0.5 });
            new Effect.Morph(this.sideExtension, { style: 'height:' + extensionHeight + 'px', duration: 0.5 });
        } else {
            new Effect.Morph(this.extension, { style: 'height: 0px', duration: 0.5 });
            new Effect.Morph(this.sideExtension, { style: 'height: 0px', duration: 0.5 });
        }
    },
    
    selectInlay: function(link) {
        if (link.tagName != 'A') link = link.up();
        var div = link.up();
        
        div.up().select('div.inlay').each(function(d) { d.removeClassName('sel'); });
        div.addClassName('sel');
        
        $('inlayName').innerHTML = link.title;
        this.inlayPart = link.rel;
        
        [this.inlayDesign, this.sideInlayDesign].each(function(div) {
            div.setStyle({
                backgroundImage: 'url(/images/inlays/' + link.rel + '.jpg)',
                opacity: 0.5
            });    
        });
        
        Effect.multiple([this.inlayDesign,this.sideInlayDesign], Effect.Appear, { duration: 0.5 });
                
        var info = this.inlayInfo[this.inlayPart];
        if (info.gallery.length > 0) {
            var links = '';
            for (var i=0, j=info.gallery.length; i<j; i++) {
                var photo = '/images/gallery/' + info.gallery[i];
                var text = '';
                if (i == 0) {
                    text = 'sample';
                    if (j > 1) {
                        text += 's (' + j + ')';
                    }
                }
                links += '<a href="' + photo + '" class="lightview" rel="gallery[' + this.inlayPart + ']" title="' + info.name + '">' + text + '</a>';
            }
            this.photoLink.innerHTML = links;
            Lightview.updateViews();
            Effect.Appear(this.photoLink, {duration: 0.5});
        } else {
            Effect.Fade(this.photoLink, {duration: 0.5});
        }

        this.refresh(false);
    },
    
    toggleCrownMoulding: function(checkbox) {
        this.showCrown = checkbox.checked;
        if (this.showCrown) {
            this.crown.show();
            this.sideCrown.show();
        } else {
            this.crown.hide();
            this.sideCrown.hide();
        }
        
        this.refresh(true);
    },
    
    toggleMeasurements: function(link) {
        if (!link.hasClassName('enabled')) {
            this.measurements.show();
            this.sideMeasurements.show();
            link.addClassName('enabled');
            link.innerHTML = 'Hide Measurements';
            Effect.Appear(this.measurements.down('.overlay'), {from: 0.0, to: 0.4});
            Effect.Appear(this.sideMeasurements.down('.overlay'), {from: 0.0, to: 0.4});
        } else {
            link.removeClassName('enabled');
            link.innerHTML = 'Show Measurements';
            
            var rulers = this.measurements.up('div.builderPage').select('div.ruler');
            for (var i=0; i<rulers.length; i++) { 
                var ruler = rulers[i];
                if (ruler.hasClassName('measure_x'))
                    new Effect.Morph(ruler, { style: 'margin-top: 0px; width: 30px; opacity: 0.0;', duration: 0.5 });
                else if (ruler.hasClassName('measure_y')) {
                    new Effect.Morph(ruler, { style: 'margin-right:0px; margin-left:0px; margin-top:0px; height: 30px; opacity: 0.0;', duration: 0.5 });
                    new Effect.Morph(ruler.down('.text'), { style: 'margin-top:10px;', duration: 0.5 });
                }
            }
            
            Effect.Fade(this.measurements.down('.overlay'), {from:0.4, to: 0.0, duration: 0.5, afterFinish: function() { this.measurements.hide(); }.bind(this)});
            Effect.Fade(this.sideMeasurements.down('.overlay'), {from:0.4, to: 0.0, duration: 0.5});
        }
        
        this.refresh(link.hasClassName('enabled'));
    },
    
    togglePartList: function(checkbox) {
        this.refresh(false);
        
        if (checkbox.checked) {
            Effect.BlindDown(this.parts, {
                afterFinish: function() {
                    this.scrollIfBelowFold(this.parts, 10);
                }.bind(this)
            });
        } else {
            Effect.BlindUp(this.parts);
        }
    },
    
    selectCorbel: function(link) {
        var div = null;
        
        if (link && link.tagName != 'A') link = link.up();
        var div = link ? link.up() : null;
        
        this.corbelSelect.select('div.corbel').each(function(d) { d.removeClassName('sel'); });
        if (div != null) div.addClassName('sel');
        
        $('corbelName').innerHTML = link ? link.title.split('-')[0].strip() : 'None';
        
        var corbelName = (!link || link.rel == 'None') ? '' : link.rel;
        this.corbel = link ? corbelName : null;
        var bgImage = 'url(/images/corbels/' + corbelName + '.jpg)';
        var sideImage = 'url(/images/corbels/' + corbelName + '_side.jpg)';
        
        this.corbelLeft.setStyle({ backgroundImage: bgImage, opacity: 0.5 });
        this.corbelRight.setStyle({ backgroundImage: bgImage, opacity: 0.5 });
        this.sideCorbel.setStyle({ backgroundImage: sideImage, opacity: 0.5 });
        
        if (this.corbel) {
            Effect.multiple([this.corbelLeft,this.corbelRight,this.sideCorbel], Effect.Appear, { duration: 0.5 });
            Effect.Appear(this.clearCorbelLink, { duration: 0.5 });
            
            var info = this.corbelInfo[this.corbel];
            if (info && info.gallery.length > 0) {
                var links = '';
                for (var i=0, j=info.gallery.length; i<j; i++) {
                    var photo = '/images/gallery/' + info.gallery[i];
                    var text = '';
                    if (i == 0) {
                        text = 'sample';
                        if (j > 1) {
                            text += 's (' + j + ')';
                        }
                    }
                    links += '<a href="' + photo + '" class="lightview" rel="gallery[' + this.corbel + ']" title="' + info.name + '">' + text + '</a>';
                }
                this.corbelPhotoLink.innerHTML = links;
                Lightview.updateViews();
                Effect.Appear(this.corbelPhotoLink, {duration: 0.5});
            } else {
                Effect.Fade(this.corbelPhotoLink, {duration: 0.5});
            }    
        } else {
            Effect.multiple([this.corbelLeft,this.corbelRight,this.sideCorbel], Effect.Fade, { duration: 0.5 });
            Effect.Fade(this.clearCorbelLink, { duration: 0.5 });
        }
        
        this.adjustOvenWidth();
        this.refresh(true);
    },
    
    selectBlower: function(element, e) {
        if (e && !(e.keyCode == Event.KEY_UP || e.keyCode == Event.KEY_DOWN)) return;
        
        if (this.blowerType.value == "IN") {
            this.blowerDuctSize.disabled = true;
            this.blowerBrand.disabled = false;
            this.blowerDuctSize.selectedIndex = this.width == 42 ? 0 : 1;
            
            this.dropdownDuctSize.show();
            this.dropdownPower.hide();
        } else if (this.blowerType.value == "EX") {
            this.blowerBrand.selectedIndex = 1;
            this.blowerBrand.disabled = true;
            this.dropdownDuctSize.hide();
            this.dropdownPower.show();
        } else {
            this.blowerDuctSize.disabled = false;
            this.blowerBrand.disabled = false;
        }
        
        this.refresh(true);
    },
    
    refreshPartsList: function() {
        var noteNum = 1;
    
        this.alt = false;  
        var partsTable = '<table><caption>Part list</caption><tr><th scope="col" style="width:3%;">Qty</th><th scope="col" style="width: 17%;">Part #</th><th scope="col" style="width:80%;">Description</th><th scope="col" style="width:5%; text-align:center;">Notes</th><th scope="col" style="width:5%;">Misc</th></tr>';
        var notesList = '';
        
        var heightCode = pad(Math.min(this.height, 10), 2, '0');
        var surround = this.width + '&rdquo;w x ' + this.hoodStyles[this.hoodStyle].heights[this.height] + '&rdquo;h surround';
        
        var surroundCode = '';
        var surroundDesc = '';
        
        if (this.hoodStyle == 'arched' && this.canopyStyle == 'radius') {
            // Versailles
            surroundCode = 'KHVERS';
            surroundDesc = 'Versailles';
        } else if (this.hoodStyle == 'angled' && this.canopyStyle == 'radius') {
            // Provence
            surroundCode = 'KHPROV';
            surroundDesc = 'Provence';
        } else if (this.hoodStyle == 'angled' && this.canopyStyle == 'inlay') {
            // Vienna
            surroundCode = 'KHVIEN';
            surroundDesc = 'Vienna';
        }
        
        surroundCode += heightCode + this.width;
        surroundDesc += ' ' + surround;
        partsTable += this.formPartRow(1, surroundCode, surroundDesc, 'Included');
        
        var attachmentList = '<ul>';
        var attachments = this.attachments[surroundCode];
        if (attachments) {
            for (var i=0; i<attachments.files.length; i++) {
                var attachment = attachments.files[i];
                attachmentList += '<li><a href="' + attachment + '">Specifications (' + surroundCode + ')</a></li>';
            }
        }
        attachmentList += '<li><a href="/Files/VillaStone - Kitchen Hood Measurement Sheet.pdf">Measurement Sheet</a></li>';
        attachmentList += '</ul>';
        this.attachmentList.innerHTML = attachmentList;
        
        if (this.extension.getHeight() > 1) {
            var numExtensions = this.height - 10;
            var extCode = 'VS12' + this.width;
            var extDesc = '12" high extension for ' + this.width + '" surround';
            partsTable += this.formPartRow(numExtensions, extCode, extDesc, 'Included');
        }
        
        if (this.inlayPart && this.canopyStyle == 'inlay') {
            var info = this.inlayInfo[this.inlayPart];
            partsTable += this.formPartRow(1, info.part, info.name, 'Included');
        }
        
        if (this.corbel) {
            partsTable += this.formPartRow(1, this.corbel, 'Corbel: ' + this.corbelInfo[this.corbel].name, 'Optional', noteNum);
            notesList += '<li><sup>' + noteNum + '</sup> Adding Corbels reduces the size of the liner to accommodate the corbel size. When corbels are selected additional framing, underside cladding, corbels and packaging are included.</li>';
            noteNum++;
        }
        
        if (this.showCrown) {
            partsTable += this.formPartRow(1, 'MCR01SET', 'Crown Molding', 'Optional', noteNum);
            //partsTable += this.formPartRow(1, 'MCR01LF', 'Molding - Crown - 5&rdquo;d x 3.5&rdquo;h x 24&rdquo;w - left return', 'Optional', noteNum);
            //partsTable += this.formPartRow(1, 'MCR01RR', 'Molding - Crown - 5&rdquo;d x 3.5&rdquo;h x 24&rdquo;w - right return', 'Optional', noteNum);
            //partsTable += this.formPartRow(1, 'MCR01ST', 'Molding - Crown - 5&rdquo;d x 3.5&rdquo;h x 24&rdquo;w - straight', 'Optional', noteNum);
            notesList += '<li><sup>' + noteNum + '</sup> When crown molding is selected. The kitchen hood will need to be lowered 3 1/2" to accommodate the crown molding height. If the height off the countertop is critical the hood canopy will need to be custom cut in the field. If this is the case please request canopy flatstock to sent as full uncut pieces.</li>';
            noteNum++;
        }
        
        var linerWidth = this.width - 6;
        var linerAdjusted = false;
        
        // Corbels affect liner width
        if (this.corbel) {
            var info = this.corbelInfo[this.corbel];
            if (info.width <= 6) {
                linerWidth -= 6; // Go down one size
                linerAdjusted = true;
            } else if (info.width > 6 && info.width <= 8) {
                linerWidth -= 12; // Go down two sizes
                linerAdjusted = true;
            }
            
            if (linerAdjusted) {
                notesList += '<li><sup>' + noteNum + '</sup> Liner adjusted to accommodate corbels.</li>';
            }
        }
        
        var brand = this.blowerBrand.value == 'TW' ? 'Tradewind' : 'Abbaka';
        var series = this.blowerBrand.value == 'TW' ? 'Professional Series ' : '';
        var brandSize = brand + ' ' + linerWidth + '" ' + series;
        var duct = this.blowerDuctSize.value + '&rdquo; duct';
        
        if (this.blowerType.value == 'IN') {
            var strengthCode = this.width == 42 ? '.6' : '1.2';
            var blowerCode = this.blowerBrand.value + linerWidth + 'IB' + strengthCode;            
            var cfm = this.width == 42 ? '660' : '1360';
            if (this.blowerBrand.value == 'AB') cfm = this.width == 42 ? '600' : '1200';
            
            var blowerDesc = brandSize + 'Liner - ' + duct + ' - ' + cfm + ' CFM Internal Blower';
            partsTable += this.formPartRow(1, blowerCode, blowerDesc, 'Included', linerAdjusted ? noteNum : null);
        } else if (this.blowerType.value == "IL") {
            var linerCode = this.blowerBrand.value + linerWidth + 'NB';
            var linerDesc = brandSize + 'Liner';
            partsTable += this.formPartRow(1, linerCode, linerDesc, 'Included', linerAdjusted ? noteNum : null);
            
            var cfm = this.blowerDuctSize.value == '8' ? '836' : '1266';
            if (this.blowerBrand.value == 'AB') cfm = this.blowerDuctSize.value == '8' ? '800' : '1200';
            var blowerCode = this.blowerBrand.value + 'B0' + pad(this.blowerDuctSize.value, 2,'0') + 'XL';
            var blowerDesc = brand + ' ' + cfm + ' CFM In-Line Blower - ' + duct + ' - with clamps';
            partsTable += this.formPartRow(1, blowerCode, blowerDesc, 'Included');
            
            if (this.blowerBrand.value == 'TW') {
                var silencerCode = 'TWS0' + pad(this.blowerDuctSize.value, 2, '0') + 'XL';
                var silencerDesc = brand + ' Duct Silencer - ' + duct;
                partsTable += this.formPartRow(1, silencerCode, silencerDesc, 'Included');
            }
        } else if (this.blowerType.value == "EX") {
            var linerCode = this.blowerBrand.value + linerWidth + 'NB';
            var linerDesc = brandSize + 'Liner';
            partsTable += this.formPartRow(1, linerCode, linerDesc, 'Included', linerAdjusted ? noteNum : null);
            
            var blowerCode = 'HYEX-' + (this.blowerPower.value == '1000' ? '1.0' : '1.4');
            var blowerDesc = 'ABBAKA External Blower - ' + this.blowerPower.value + 'cfm';
            partsTable += this.formPartRow(1, blowerCode, blowerDesc, 'Included', null);
        }
        
        partsTable += '</table>';
        $('partTable').innerHTML = partsTable;
        
        if (notesList != '') {
            notesList = '<ul>' + notesList + '</ul>';
        }
        $('noteList').innerHTML = notesList;
    },
    
    formPartRow: function(qty, part, description, notes, other) {
        if (notes == 'Optional') {
            notes = '<span class="optional">' + notes + '</span>';
        }
    
        notes = notes || '';
        var altClass = this.alt ? ' class="alt"' : '';
        this.alt = !this.alt;
        return '<tr' + altClass + '><td class="center">1</td><td>' + part + '</td><td>' + description + '</td><td class="center notes">' + notes + '</td><td class="center"><sup>' + (other ? other : '') + '</sup></td></tr>';    
    },
    
    getCorbelWidths: function() {
        if (this.corbel) {
            var inlayPos = this.canopy.positionedOffset();
            var corbel = this.corbelInfo[this.corbel];
            
            var width = this.width * PixelsPerInch;
            width -= corbel.width * PixelsPerInch * 2;
            width -= 14;
            widthBetweenCorbels = this.width - 2 - (corbel.width * 2);
            return { corbelWidth: width, between: widthBetweenCorbels };
        } else {
            return false;
        }
    },
    
    refreshMeasurements: function() {
        if (!this.measurements.visible()) return;
        var inlayPos = this.canopy.positionedOffset();
        
        var corbelWidths = false;
        
        if (this.corbel) {
            var corbel = this.corbelInfo[this.corbel];
            
            var topMargin = inlayPos.top + this.canopyStyles[this.canopyStyle].height.pixels;
            topMargin += (corbel.height * PixelsPerInch) / 2;
            topMargin -= 5;
            
            corbelWidths = this.getCorbelWidths();
            
            this.rulerCorbelSpacing.setOpacity(1.0);
            this.rulerCorbelSpacing.show();
            
            this.rulerCorbelSpacing.down('.text').innerHTML = corbelWidths.between + "&rdquo;"
            new Effect.Morph(this.rulerCorbelSpacing, { style: "margin-top: " + topMargin + "px; width: " + corbelWidths.corbelWidth + "px;", duration: 0.5 });
        } else {
            this.rulerCorbelSpacing.hide();
        }
        
        var inlayWidth = this.width * PixelsPerInch;
        this.rulerInlayWidth.down('.text').innerHTML = this.width + "&rdquo;";
        new Effect.Morph(this.rulerInlayWidth, { style: 'margin-top:' + (inlayPos.top - 10) + 'px; width: ' + inlayWidth + 'px; opacity: 1.0;', duration: 0.5 });
        
        var inlayBottomWidth = inlayWidth - 2*PixelsPerInch - 4;
        this.rulerInlayBottom.down('.text').innerHTML = (this.width - 2) + "&rdquo;";
        new Effect.Morph(this.rulerInlayBottom, { style: 'margin-top:' + (inlayPos.top + this.canopyStyles[this.canopyStyle].height.pixels - 3) + 'px; width: ' + inlayBottomWidth + 'px; opacity: 1.0;', duration: 0.5 });
        
        var hoodPos = this.hood.positionedOffset().top;
        var topOffset = this.showCrown ? -4 : 1;
        var topWidthIn = this.height < 9 ? (this.width - 16) : (this.width - 22);
        var topWidth = topWidthIn * PixelsPerInch - (this.height < 9 ? 0 : 2);
        this.rulerTopWidth.down('.text').innerHTML = topWidthIn + "&rdquo;";
        new Effect.Morph(this.rulerTopWidth, { style: 'margin-top:' + (hoodPos + topOffset) + 'px; width: ' + topWidth + 'px; opacity: 1.0;', duration: 0.5 });
        
        var inlayHeightX = inlayPos.left - 6;
        var inlayHeightY = inlayPos.top;
        new Effect.Morph(this.rulerInlayHeight, { style: 'margin-top:' + inlayHeightY + 'px; margin-left: '  + inlayHeightX + 'px; height: ' + this.canopyStyles[this.canopyStyle].height.pixels + 'px; opacity: 1.0;', duration: 0.5 });
        this.rulerInlayHeight.down('span.text').innerHTML = (this.canopyStyle == 'radius' ? '15' : '10&frac14;') + '&rdquo';
        
        var systemHeight = 0;
        if (this.showCrown) systemHeight += CrownHeight;
        if (this.height > 10 && this.width > 48) systemHeight += (this.height-10) * ExtensionHeight;
        systemHeight += this.hoodHeightsPrecise[this.height];
        systemHeight += this.canopyStyles[this.canopyStyle].height.inches;
        var systemHeightPx = systemHeight * PixelsPerInch;
        
        if (this.height > 9) systemHeightPx -= 4;
        if (this.showCrown) systemHeightPx -= 2;
        
        var sysHeightText = this.rulerSystemHeight.down('.text');
        sysHeightText.innerHTML = systemHeight + "&rdquo;";
        var rightRulerPos = (BuilderWidth - inlayPos.left - this.canopy.getWidth()) - 14;
        
        new Effect.Morph(sysHeightText, { style: 'margin-top:' + (systemHeightPx/3) + 'px;', duration: 0.5 });
        new Effect.Morph(this.rulerSystemHeight, { style: 'height: ' + systemHeightPx + 'px; margin-right: ' + rightRulerPos + 'px; opacity: 1.0', duration: 0.5 });
        
        var heightOffFloor = (this.height * InchesPerFoot) - systemHeight;
        var heightOffFloorPx = (this.height * InchesPerFoot * PixelsPerInch) - systemHeightPx;
        
        var sysFloorHeightText = this.rulerFloorHeight.down('.text');
        sysFloorHeightText.innerHTML = heightOffFloor + "&rdquo;";
        new Effect.Morph(sysFloorHeightText, { style: 'margin-top:' + (heightOffFloorPx/3) + 'px;', duration: 0.5 });
        new Effect.Morph(this.rulerFloorHeight, { style: 'height: ' + heightOffFloorPx + 'px; margin-right: ' + rightRulerPos + 'px; margin-top: ' + (systemHeightPx-1) + 'px; opacity: 1.0', duration: 0.5 });
        
        this.rulerSideTop.down('.text').innerHTML = (this.height == 8 ? 18 : (this.hoodStyle == 'arched' ? 14.5 : 13)) + '&rdquo;';
        new Effect.Morph(this.rulerSideTop, { style: 'margin-top: ' + (hoodPos + topOffset) + 'px; margin-left: ' + (this.hoodStyle == 'arched' ? 98 : (this.height == 8 ? 86 : 105)) + 'px; width:' + (this.hoodStyle == 'arched' ? 58 : (this.height == 8 ? 70 : 51)) + 'px; opacity: 1.0;', duration: 0.5 });
        new Effect.Morph(this.rulerSideBottom, { style: 'margin-top:' + (inlayPos.top - 10) + 'px; width:110px; margin-left: 46px; opacity: 1.0;', duration: 0.5 });
        new Effect.Morph(this.rulerSideInlayBottom, { style: 'margin-top:' + (inlayPos.top + this.canopyStyles[this.canopyStyle].height.pixels - 2) + 'px; width:103px; margin-left: 53px; opacity:1.0;', duration: 0.5 });
        
        var stoveWidth = this.adjustOvenWidth().ovenWidth;
        this.rulerStoveWidth.down('.text').innerHTML = stoveWidth + "&rdquo;";
        new Effect.Morph(this.rulerStoveWidth, { style: 'margin-top:' + (inlayPos.top + this.canopyStyles[this.canopyStyle].height.pixels + 220) + 'px; width: ' + stoveWidth * PixelsPerInch + 'px; opacity: 1.0;', duration: 0.5 });
    },
    
    scrollIfBelowFold: function(element, offset, options) {
	    if (!element) { return; }
	
	    var scrollOffsets = document.viewport.getScrollOffsets();
        var yFold = document.viewport.getHeight() + scrollOffsets.top;
        var yElem = element.cumulativeOffset()[1] + element.getHeight();
        
        if (offset) {
            yElem += offset;
        }
                 
        if (yElem > yFold) {
            new Effect.Tween(null, scrollOffsets.top, scrollOffsets.top+(yElem-yFold), { duration: 0.80 },
                function(p) { scrollTo(scrollOffsets.left, p.round()) }
            );
        }
	}
});