use crate::wgpuctx::WgpuCtx;

pub struct Texture
{
    texture: wgpu::Texture,
    view: wgpu::TextureView,
    sampler: wgpu::Sampler,
    pub bindgrouplayout: wgpu::BindGroupLayout,
    bindgroup: wgpu::BindGroup,
}

impl Texture
{
    pub fn new(
        device: &wgpu::Device,
        descr: wgpu::TextureDescriptor)
    -> Self
    {
        let texture = device.create_texture(&descr);
        let view = texture.create_view(&wgpu::TextureViewDescriptor::default());
        let sampler = device.create_sampler(
            &wgpu::SamplerDescriptor {
                address_mode_u: wgpu::AddressMode::Repeat,
                address_mode_v: wgpu::AddressMode::Repeat,
                address_mode_w: wgpu::AddressMode::ClampToEdge,
                mag_filter: wgpu::FilterMode::Linear,
                min_filter: wgpu::FilterMode::Nearest,
                mipmap_filter: wgpu::FilterMode::Nearest,
                ..Default::default()
            }
        );

        let bind_group_layout = device.create_bind_group_layout(
            &wgpu::BindGroupLayoutDescriptor {
                label: None,
                entries: &[
                    wgpu::BindGroupLayoutEntry {
                        binding: 0,
                        visibility: wgpu::ShaderStages::FRAGMENT,
                        ty: wgpu::BindingType::Texture { 
                            sample_type: wgpu::TextureSampleType::Float {
                                filterable: true
                            }, 
                            view_dimension: wgpu::TextureViewDimension::D2, 
                            multisampled: false
                        },
                        count: None
                    },
                    wgpu::BindGroupLayoutEntry {
                        binding: 1,
                        visibility: wgpu::ShaderStages::FRAGMENT,
                        ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering),
                        count: None
                    }
                ]
            }
        );

        let bind_group = device.create_bind_group(
            &wgpu::BindGroupDescriptor {
                label: None,
                layout: &bind_group_layout,
                entries: &[
                    wgpu::BindGroupEntry {
                        binding: 0,
                        resource: wgpu::BindingResource::TextureView(&view)
                    },
                    wgpu::BindGroupEntry {
                        binding: 1,
                        resource: wgpu::BindingResource::Sampler(&sampler)
                    }
                ]
            }
        );

        Self {
            texture: texture,
            view: view,
            sampler: sampler,
            bindgrouplayout: bind_group_layout,
            bindgroup: bind_group,
        }
    }

    pub fn view(&self)
    -> &wgpu::TextureView
    { &self.view }

    pub fn use_on_pass(
        &self,
        pass: &mut wgpu::RenderPass,
        index: u32)
    {
        pass.set_bind_group(index, &self.bindgroup, &[]);
    }
} // impl Texture
